Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / GridViewColumn.cs / 1305600 / GridViewColumn.cs
//---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System.ComponentModel; // DesignerSerializationVisibility using System.Diagnostics; using System.Windows.Data; // BindingBase using System.Windows.Markup; // [ContentProperty] using MS.Internal; // Helper namespace System.Windows.Controls { ////// template of column of a details view. /// [ContentProperty("Header")] [StyleTypedProperty(Property = "HeaderContainerStyle", StyleTargetType = typeof(System.Windows.Controls.GridViewColumnHeader))] [Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)] // cannot be read & localized as string public class GridViewColumn : DependencyObject, INotifyPropertyChanged { //------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------- #region Constructors ////// constructor /// public GridViewColumn() { ResetPrivateData(); // Descendant of this class can override the metadata to give it // a value other than NaN and without trigger the propertychange // callback and thus, result in _state be out-of-[....] with the // Width property. _state = Double.IsNaN(Width) ? ColumnMeasureState.Init : ColumnMeasureState.SpecificWidth; } #endregion //-------------------------------------------------------------------- // // Public Methods // //------------------------------------------------------------------- #region Public Methods ////// Returns a string representation of this object. /// ///public override string ToString() { return SR.Get(SRID.ToStringFormatString_GridViewColumn, this.GetType(), Header); } #endregion //-------------------------------------------------------------------- // // Public Properties // //-------------------------------------------------------------------- #region Public Properties // For all the DPs on GridViewColumn, null is treated as unset, // because it's impossible to distinguish null and unset. // Change a property between null and unset, PropertyChangedCallback will not be called. #region Header /// /// Header DependencyProperty /// public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register( "Header", typeof(object), typeof(GridViewColumn), new FrameworkPropertyMetadata( new PropertyChangedCallback(OnHeaderChanged)) ); ////// If provide a GridViewColumnHeader or an instance of its sub class , it will be used as header. /// Otherwise, it will be used as content of header /// ////// typical usage is to assign the content of the header or the container /// public object Header { get { return GetValue(HeaderProperty); } set { SetValue(HeaderProperty, value); } } private static void OnHeaderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { GridViewColumn c = (GridViewColumn)d; c.OnPropertyChanged(HeaderProperty.Name); } #endregion Header #region HeaderContainerStyle ////// GridViewColumn column = new GridViewColumn(); /// column.Header = "Name"; ///
/// or ////// GridViewColumnHeader header = new GridViewColumnHeader(); /// header.Content = "Name"; /// header.Click += ... /// ... /// GridViewColumn column = new GridViewColumn(); /// column.Header = header; ///
////// HeaderContainerStyle DependencyProperty /// public static readonly DependencyProperty HeaderContainerStyleProperty = DependencyProperty.Register( "HeaderContainerStyle", typeof(Style), typeof(GridViewColumn), new FrameworkPropertyMetadata( new PropertyChangedCallback(OnHeaderContainerStyleChanged)) ); ////// Header container's style /// public Style HeaderContainerStyle { get { return (Style)GetValue(HeaderContainerStyleProperty); } set { SetValue(HeaderContainerStyleProperty, value); } } private static void OnHeaderContainerStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { GridViewColumn c = (GridViewColumn)d; c.OnPropertyChanged(HeaderContainerStyleProperty.Name); } #endregion HeaderContainerStyle #region HeaderTemplate ////// HeaderTemplate DependencyProperty /// public static readonly DependencyProperty HeaderTemplateProperty = DependencyProperty.Register( "HeaderTemplate", typeof(DataTemplate), typeof(GridViewColumn), new FrameworkPropertyMetadata( new PropertyChangedCallback(OnHeaderTemplateChanged)) ); ////// column header template /// public DataTemplate HeaderTemplate { get { return (DataTemplate)GetValue(HeaderTemplateProperty); } set { SetValue(HeaderTemplateProperty, value); } } private static void OnHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { GridViewColumn c = (GridViewColumn)d; // Check to prevent Template and TemplateSelector at the same time Helper.CheckTemplateAndTemplateSelector("Header", HeaderTemplateProperty, HeaderTemplateSelectorProperty, c); c.OnPropertyChanged(HeaderTemplateProperty.Name); } #endregion HeaderTemplate #region HeaderTemplateSelector ////// HeaderTemplateSelector DependencyProperty /// public static readonly DependencyProperty HeaderTemplateSelectorProperty = DependencyProperty.Register( "HeaderTemplateSelector", typeof(DataTemplateSelector), typeof(GridViewColumn), new FrameworkPropertyMetadata( new PropertyChangedCallback(OnHeaderTemplateSelectorChanged)) ); ////// header template selector /// ////// This property is ignored if [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public DataTemplateSelector HeaderTemplateSelector { get { return (DataTemplateSelector)GetValue(HeaderTemplateSelectorProperty); } set { SetValue(HeaderTemplateSelectorProperty, value); } } private static void OnHeaderTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { GridViewColumn c = (GridViewColumn)d; // Check to prevent Template and TemplateSelector at the same time Helper.CheckTemplateAndTemplateSelector("Header", HeaderTemplateProperty, HeaderTemplateSelectorProperty, c); c.OnPropertyChanged(HeaderTemplateSelectorProperty.Name); } #endregion HeaderTemplateSelector #region HeaderStringFormat ///is set. /// /// The DependencyProperty for the HeaderStringFormat property. /// Flags: None /// Default Value: null /// public static readonly DependencyProperty HeaderStringFormatProperty = DependencyProperty.Register( "HeaderStringFormat", typeof(String), typeof(GridViewColumn), new FrameworkPropertyMetadata( (String) null, new PropertyChangedCallback(OnHeaderStringFormatChanged))); ////// HeaderStringFormat is the format used to display the header content as a string. /// This arises only when no template is available. /// public String HeaderStringFormat { get { return (String) GetValue(HeaderStringFormatProperty); } set { SetValue(HeaderStringFormatProperty, value); } } ////// Called when HeaderStringFormatProperty is invalidated on "d." /// private static void OnHeaderStringFormatChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { GridViewColumn ctrl = (GridViewColumn)d; ctrl.OnHeaderStringFormatChanged((String) e.OldValue, (String) e.NewValue); } ////// This method is invoked when the HeaderStringFormat property changes. /// /// The old value of the HeaderStringFormat property. /// The new value of the HeaderStringFormat property. protected virtual void OnHeaderStringFormatChanged(String oldHeaderStringFormat, String newHeaderStringFormat) { } #endregion HeaderStringFormat #region DisplayMemberBinding ////// BindingBase is be used to generate each cell of this column. /// Set to null make this property do not work. /// public BindingBase DisplayMemberBinding { get { return _displayMemberBinding; } set { if (_displayMemberBinding != value) { _displayMemberBinding = value; OnDisplayMemberBindingChanged(); } } } private BindingBase _displayMemberBinding; ////// If DisplayMemberBinding property changed, NotifyPropertyChanged event will be raised with this string. /// internal const string c_DisplayMemberBindingName = "DisplayMemberBinding"; private void OnDisplayMemberBindingChanged() { OnPropertyChanged(c_DisplayMemberBindingName); } #endregion #region CellTemplate ////// CellTemplate DependencyProperty /// public static readonly DependencyProperty CellTemplateProperty = DependencyProperty.Register( "CellTemplate", typeof(DataTemplate), typeof(GridViewColumn), new PropertyMetadata( new PropertyChangedCallback(OnCellTemplateChanged)) ); ////// template for this column's item UI /// public DataTemplate CellTemplate { get { return (DataTemplate)GetValue(CellTemplateProperty); } set { SetValue(CellTemplateProperty, value); } } private static void OnCellTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { GridViewColumn c = (GridViewColumn)d; c.OnPropertyChanged(CellTemplateProperty.Name); } #endregion #region CellTemplateSelector ////// CellTemplateSelector DependencyProperty /// public static readonly DependencyProperty CellTemplateSelectorProperty = DependencyProperty.Register( "CellTemplateSelector", typeof(DataTemplateSelector), typeof(GridViewColumn), new PropertyMetadata( new PropertyChangedCallback(OnCellTemplateSelectorChanged)) ); ////// templateSelector for this column's item UI /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public DataTemplateSelector CellTemplateSelector { get { return (DataTemplateSelector)GetValue(CellTemplateSelectorProperty); } set { SetValue(CellTemplateSelectorProperty, value); } } private static void OnCellTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { GridViewColumn c = (GridViewColumn)d; c.OnPropertyChanged(CellTemplateSelectorProperty.Name); } #endregion #region Width ////// Width DependencyProperty /// public static readonly DependencyProperty WidthProperty = FrameworkElement.WidthProperty.AddOwner( typeof(GridViewColumn), new PropertyMetadata( Double.NaN /* default value */, new PropertyChangedCallback(OnWidthChanged)) ); ////// width of the column /// ////// The default value is Double.NaN which means size to max visible item width. /// [TypeConverter(typeof(LengthConverter))] public double Width { get { return (double)GetValue(WidthProperty); } set { SetValue(WidthProperty, value); } } private static void OnWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { GridViewColumn c = (GridViewColumn)d; double newWidth = (double)e.NewValue; // reset DesiredWidth if width is set to auto c.State = Double.IsNaN(newWidth) ? ColumnMeasureState.Init : ColumnMeasureState.SpecificWidth; c.OnPropertyChanged(WidthProperty.Name); } #endregion #region ActualWidth ////// actual width of this column /// public double ActualWidth { get { return _actualWidth; } private set { if (Double.IsNaN(value) || Double.IsInfinity(value) || value < 0.0) { Debug.Assert(false, "Invalid value for ActualWidth."); } else if (_actualWidth != value) { _actualWidth = value; OnPropertyChanged(c_ActualWidthName); } } } #endregion #endregion Public Properties #region INotifyPropertyChanged ////// PropertyChanged event (per event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged { add { _propertyChanged += value; } remove { _propertyChanged -= value; } } private event PropertyChangedEventHandler _propertyChanged; #endregion INotifyPropertyChanged //------------------------------------------------------------------- // // Protected Methods // //-------------------------------------------------------------------- #region Protected Methods ///). /// /// Raise INotifyPropertyChanged.PropertyChanged event. /// /// event arguments with name of the changed property protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) { if (_propertyChanged != null) { _propertyChanged(this, e); } } #endregion //------------------------------------------------------------------- // // Internal Methodes // //------------------------------------------------------------------- #region Internal Methodes // Propagate theme changes to contained headers internal void OnThemeChanged() { if (Header != null) { DependencyObject d = Header as DependencyObject; if (d != null) { FrameworkElement fe; FrameworkContentElement fce; Helper.DowncastToFEorFCE(d, out fe, out fce, false); if (fe != null || fce != null) { TreeWalkHelper.InvalidateOnResourcesChange(fe, fce, ResourcesChangeInfo.ThemeChangeInfo); } } } } ////// ensure final column width is no less than a value /// internal double EnsureWidth(double width) { if (width > DesiredWidth) { DesiredWidth = width; } return DesiredWidth; } ////// column collection should call this when remove a column from the collection. /// internal void ResetPrivateData() { _actualIndex = -1; _desiredWidth = 0.0; _state = Double.IsNaN(Width) ? ColumnMeasureState.Init : ColumnMeasureState.SpecificWidth; } #endregion //------------------------------------------------------------------- // // Internal Properties // //-------------------------------------------------------------------- #region Internal Properties ////// Reachable State Transition Diagram: /// /// +- - - - - - - - - - + /// | Init | /// +- - - - - - - - - - + /// / /| A |\ \ /// / / | \ \ /// / / | \ \ /// / / | \ \ /// / / | \ \ /// / / | \ \ /// / / | \ \ /// |/ / | \ \| /// +--------------------+ | +--------------------+ /// | Headered |--------+------->| Data | /// +--------------------+ | +--------------------+ /// \ | / /// \ | / /// \ | / /// \ | / /// \ | / /// \ | / /// \| | |/ /// +--------------------+ /// | SpecificWidth | /// +--------------------+ /// /// Note: /// /// 1) Init is a intermidiated state, that is a column should not stop on such a state; /// 2) Headered, Data and SpecificWidth are terminal state, that is a column can stop at /// the state if no further data change / user interaction to trigger a change. /// /// Typical state transiton flows: /// /// Case 1: column is auto, LV has header and data /// Init --> [ Headered --> ] Data /// /// Case 2: column is auto, LV has header but no data /// Init --> Headered /// /// Case 3: column has a specified width /// SpecificWidth /// /// Case 4: couble click a column of case 3 /// SpecificWidth --> Init --> Headered / Data (depends on the data) /// /// Case 5: resize a column which has width as auto /// Headered / Data --> SpecificWidth /// /// internal ColumnMeasureState State { get { return _state; } set { if (_state != value) { _state = value; if (value != ColumnMeasureState.Init) // Headered, Data or SpecificWidth { UpdateActualWidth(); } else { DesiredWidth = 0.0; } } else if (value == ColumnMeasureState.SpecificWidth) { UpdateActualWidth(); } } } // NOTE: Perf optimization. To avoid re-search index again and again // by every GridViewRowPresenter, add an index here. internal int ActualIndex { get { return _actualIndex; } set { _actualIndex = value; } } ////// Minimum width requirement for this column. Shared by all visible cells in this column /// ////// Below table shows an example of how column width is shared: /// /// 1. In the first round of layout, DesiredWidth continue to grow when each row comes into measure /// /// 2. after the 1st round, the desired width for this column is decided, each row on layout updated /// with check this value with its copy of maxDesiredWidth, if not equal, triger another round of /// measure. /// /// 3. after 2nd round of layout, all rows should be in same size. /// +------------+-----------+--------------+------------+------------+-------------+ /// | | Width | Cell | Desired | Presenter | Column | /// | | | DesiredWidth | Width | LocalCopy | State | /// |------------+-----------+--------------+------------+------------|-------------| /// | 1st round | NaN | | 10.0 | | Init | /// | | | | | | | /// | (row 1) | | 12.0 | 12.0 | | | /// | (row 2) | | 70.0 | 70.0 | | | /// | (row 3) | | 80.0 | 80.0 | | | /// | (row 4) | | 60.0 | 80.0 | | | /// |------------+-----------+--------------+------------+------------|-------------| /// | layout | NaN | | | | | /// | updated | | | | | | /// | | | | | | | /// | [hdr_row] | | | | | [Headered]* | /// | | | | | | | /// | (row 1) | | | 80.0 | 12.0 | Data | /// | (row 2) | | | 80.0 | 70.0 | | /// | (row 3) | | | 80.0 | 80.0 | | /// | (row 4) | | | 80.0 | 80.0 | | /// |------------+-----------+--------------+------------+------------|-------------| /// | 2nd round | NaN | | | | | /// | | | | | | | /// | (row 1) | | 12.0 | 80.0 | 80.0 | | /// | (row 2) | | 70.0 | 80.0 | 80.0 | | /// +------------+-----------+--------------+------------+------------+-------------+ /// /// * Depends on the tree structure, it is possible that HeaderRowPresenter accomplish first /// layout first. So the column state can be Headered for a while. But will be changed to /// 'Data' once a data row accomplish its first layout. /// /// internal double DesiredWidth { get { return _desiredWidth; } private set { _desiredWidth = value; } } internal const string c_ActualWidthName = "ActualWidth"; #endregion #region InheritanceContext ////// InheritanceContext /// internal override DependencyObject InheritanceContext { get { return _inheritanceContext; } } // Receive a new inheritance context internal override void AddInheritanceContext(DependencyObject context, DependencyProperty property) { // reinforce that no one can compete to be mentor of this element. if (_inheritanceContext == null && context != null) { // Pick up the new context _inheritanceContext = context; OnInheritanceContextChanged(EventArgs.Empty); } } // Remove an inheritance context internal override void RemoveInheritanceContext(DependencyObject context, DependencyProperty property) { if (_inheritanceContext == context) { // clear the context _inheritanceContext = null; OnInheritanceContextChanged(EventArgs.Empty); } } // Fields to implement DO's inheritance context DependencyObject _inheritanceContext; #endregion InheritanceContext //------------------------------------------------------------------- // // Private Methods / Fields // //-------------------------------------------------------------------- #region Private Methods ////// Helper to raise INotifyPropertyChanged.PropertyChanged event /// /// Name of the changed property private void OnPropertyChanged(string propertyName) { OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); } ////// force ActualWidth to be reevaluated /// private void UpdateActualWidth() { ActualWidth = (State == ColumnMeasureState.SpecificWidth) ? Width : DesiredWidth; } #endregion #region Private Fields private double _desiredWidth; private int _actualIndex; private double _actualWidth; private ColumnMeasureState _state; #endregion } ////// States of column when doing layout /// See GridViewColumn.State for reachable state transition diagram /// internal enum ColumnMeasureState { ////// Column width is just initialized and will size to content width /// Init = 0, ////// Column width reach max desired width of header(s) in this column /// Headered = 1, ////// Column width reach max desired width of data row(s) in this column /// Data = 2, ////// Column has a specific value as width /// SpecificWidth = 3 } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System.ComponentModel; // DesignerSerializationVisibility using System.Diagnostics; using System.Windows.Data; // BindingBase using System.Windows.Markup; // [ContentProperty] using MS.Internal; // Helper namespace System.Windows.Controls { ////// template of column of a details view. /// [ContentProperty("Header")] [StyleTypedProperty(Property = "HeaderContainerStyle", StyleTargetType = typeof(System.Windows.Controls.GridViewColumnHeader))] [Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)] // cannot be read & localized as string public class GridViewColumn : DependencyObject, INotifyPropertyChanged { //------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------- #region Constructors ////// constructor /// public GridViewColumn() { ResetPrivateData(); // Descendant of this class can override the metadata to give it // a value other than NaN and without trigger the propertychange // callback and thus, result in _state be out-of-[....] with the // Width property. _state = Double.IsNaN(Width) ? ColumnMeasureState.Init : ColumnMeasureState.SpecificWidth; } #endregion //-------------------------------------------------------------------- // // Public Methods // //------------------------------------------------------------------- #region Public Methods ////// Returns a string representation of this object. /// ///public override string ToString() { return SR.Get(SRID.ToStringFormatString_GridViewColumn, this.GetType(), Header); } #endregion //-------------------------------------------------------------------- // // Public Properties // //-------------------------------------------------------------------- #region Public Properties // For all the DPs on GridViewColumn, null is treated as unset, // because it's impossible to distinguish null and unset. // Change a property between null and unset, PropertyChangedCallback will not be called. #region Header /// /// Header DependencyProperty /// public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register( "Header", typeof(object), typeof(GridViewColumn), new FrameworkPropertyMetadata( new PropertyChangedCallback(OnHeaderChanged)) ); ////// If provide a GridViewColumnHeader or an instance of its sub class , it will be used as header. /// Otherwise, it will be used as content of header /// ////// typical usage is to assign the content of the header or the container /// public object Header { get { return GetValue(HeaderProperty); } set { SetValue(HeaderProperty, value); } } private static void OnHeaderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { GridViewColumn c = (GridViewColumn)d; c.OnPropertyChanged(HeaderProperty.Name); } #endregion Header #region HeaderContainerStyle ////// GridViewColumn column = new GridViewColumn(); /// column.Header = "Name"; ///
/// or ////// GridViewColumnHeader header = new GridViewColumnHeader(); /// header.Content = "Name"; /// header.Click += ... /// ... /// GridViewColumn column = new GridViewColumn(); /// column.Header = header; ///
////// HeaderContainerStyle DependencyProperty /// public static readonly DependencyProperty HeaderContainerStyleProperty = DependencyProperty.Register( "HeaderContainerStyle", typeof(Style), typeof(GridViewColumn), new FrameworkPropertyMetadata( new PropertyChangedCallback(OnHeaderContainerStyleChanged)) ); ////// Header container's style /// public Style HeaderContainerStyle { get { return (Style)GetValue(HeaderContainerStyleProperty); } set { SetValue(HeaderContainerStyleProperty, value); } } private static void OnHeaderContainerStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { GridViewColumn c = (GridViewColumn)d; c.OnPropertyChanged(HeaderContainerStyleProperty.Name); } #endregion HeaderContainerStyle #region HeaderTemplate ////// HeaderTemplate DependencyProperty /// public static readonly DependencyProperty HeaderTemplateProperty = DependencyProperty.Register( "HeaderTemplate", typeof(DataTemplate), typeof(GridViewColumn), new FrameworkPropertyMetadata( new PropertyChangedCallback(OnHeaderTemplateChanged)) ); ////// column header template /// public DataTemplate HeaderTemplate { get { return (DataTemplate)GetValue(HeaderTemplateProperty); } set { SetValue(HeaderTemplateProperty, value); } } private static void OnHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { GridViewColumn c = (GridViewColumn)d; // Check to prevent Template and TemplateSelector at the same time Helper.CheckTemplateAndTemplateSelector("Header", HeaderTemplateProperty, HeaderTemplateSelectorProperty, c); c.OnPropertyChanged(HeaderTemplateProperty.Name); } #endregion HeaderTemplate #region HeaderTemplateSelector ////// HeaderTemplateSelector DependencyProperty /// public static readonly DependencyProperty HeaderTemplateSelectorProperty = DependencyProperty.Register( "HeaderTemplateSelector", typeof(DataTemplateSelector), typeof(GridViewColumn), new FrameworkPropertyMetadata( new PropertyChangedCallback(OnHeaderTemplateSelectorChanged)) ); ////// header template selector /// ////// This property is ignored if [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public DataTemplateSelector HeaderTemplateSelector { get { return (DataTemplateSelector)GetValue(HeaderTemplateSelectorProperty); } set { SetValue(HeaderTemplateSelectorProperty, value); } } private static void OnHeaderTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { GridViewColumn c = (GridViewColumn)d; // Check to prevent Template and TemplateSelector at the same time Helper.CheckTemplateAndTemplateSelector("Header", HeaderTemplateProperty, HeaderTemplateSelectorProperty, c); c.OnPropertyChanged(HeaderTemplateSelectorProperty.Name); } #endregion HeaderTemplateSelector #region HeaderStringFormat ///is set. /// /// The DependencyProperty for the HeaderStringFormat property. /// Flags: None /// Default Value: null /// public static readonly DependencyProperty HeaderStringFormatProperty = DependencyProperty.Register( "HeaderStringFormat", typeof(String), typeof(GridViewColumn), new FrameworkPropertyMetadata( (String) null, new PropertyChangedCallback(OnHeaderStringFormatChanged))); ////// HeaderStringFormat is the format used to display the header content as a string. /// This arises only when no template is available. /// public String HeaderStringFormat { get { return (String) GetValue(HeaderStringFormatProperty); } set { SetValue(HeaderStringFormatProperty, value); } } ////// Called when HeaderStringFormatProperty is invalidated on "d." /// private static void OnHeaderStringFormatChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { GridViewColumn ctrl = (GridViewColumn)d; ctrl.OnHeaderStringFormatChanged((String) e.OldValue, (String) e.NewValue); } ////// This method is invoked when the HeaderStringFormat property changes. /// /// The old value of the HeaderStringFormat property. /// The new value of the HeaderStringFormat property. protected virtual void OnHeaderStringFormatChanged(String oldHeaderStringFormat, String newHeaderStringFormat) { } #endregion HeaderStringFormat #region DisplayMemberBinding ////// BindingBase is be used to generate each cell of this column. /// Set to null make this property do not work. /// public BindingBase DisplayMemberBinding { get { return _displayMemberBinding; } set { if (_displayMemberBinding != value) { _displayMemberBinding = value; OnDisplayMemberBindingChanged(); } } } private BindingBase _displayMemberBinding; ////// If DisplayMemberBinding property changed, NotifyPropertyChanged event will be raised with this string. /// internal const string c_DisplayMemberBindingName = "DisplayMemberBinding"; private void OnDisplayMemberBindingChanged() { OnPropertyChanged(c_DisplayMemberBindingName); } #endregion #region CellTemplate ////// CellTemplate DependencyProperty /// public static readonly DependencyProperty CellTemplateProperty = DependencyProperty.Register( "CellTemplate", typeof(DataTemplate), typeof(GridViewColumn), new PropertyMetadata( new PropertyChangedCallback(OnCellTemplateChanged)) ); ////// template for this column's item UI /// public DataTemplate CellTemplate { get { return (DataTemplate)GetValue(CellTemplateProperty); } set { SetValue(CellTemplateProperty, value); } } private static void OnCellTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { GridViewColumn c = (GridViewColumn)d; c.OnPropertyChanged(CellTemplateProperty.Name); } #endregion #region CellTemplateSelector ////// CellTemplateSelector DependencyProperty /// public static readonly DependencyProperty CellTemplateSelectorProperty = DependencyProperty.Register( "CellTemplateSelector", typeof(DataTemplateSelector), typeof(GridViewColumn), new PropertyMetadata( new PropertyChangedCallback(OnCellTemplateSelectorChanged)) ); ////// templateSelector for this column's item UI /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public DataTemplateSelector CellTemplateSelector { get { return (DataTemplateSelector)GetValue(CellTemplateSelectorProperty); } set { SetValue(CellTemplateSelectorProperty, value); } } private static void OnCellTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { GridViewColumn c = (GridViewColumn)d; c.OnPropertyChanged(CellTemplateSelectorProperty.Name); } #endregion #region Width ////// Width DependencyProperty /// public static readonly DependencyProperty WidthProperty = FrameworkElement.WidthProperty.AddOwner( typeof(GridViewColumn), new PropertyMetadata( Double.NaN /* default value */, new PropertyChangedCallback(OnWidthChanged)) ); ////// width of the column /// ////// The default value is Double.NaN which means size to max visible item width. /// [TypeConverter(typeof(LengthConverter))] public double Width { get { return (double)GetValue(WidthProperty); } set { SetValue(WidthProperty, value); } } private static void OnWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { GridViewColumn c = (GridViewColumn)d; double newWidth = (double)e.NewValue; // reset DesiredWidth if width is set to auto c.State = Double.IsNaN(newWidth) ? ColumnMeasureState.Init : ColumnMeasureState.SpecificWidth; c.OnPropertyChanged(WidthProperty.Name); } #endregion #region ActualWidth ////// actual width of this column /// public double ActualWidth { get { return _actualWidth; } private set { if (Double.IsNaN(value) || Double.IsInfinity(value) || value < 0.0) { Debug.Assert(false, "Invalid value for ActualWidth."); } else if (_actualWidth != value) { _actualWidth = value; OnPropertyChanged(c_ActualWidthName); } } } #endregion #endregion Public Properties #region INotifyPropertyChanged ////// PropertyChanged event (per event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged { add { _propertyChanged += value; } remove { _propertyChanged -= value; } } private event PropertyChangedEventHandler _propertyChanged; #endregion INotifyPropertyChanged //------------------------------------------------------------------- // // Protected Methods // //-------------------------------------------------------------------- #region Protected Methods ///). /// /// Raise INotifyPropertyChanged.PropertyChanged event. /// /// event arguments with name of the changed property protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) { if (_propertyChanged != null) { _propertyChanged(this, e); } } #endregion //------------------------------------------------------------------- // // Internal Methodes // //------------------------------------------------------------------- #region Internal Methodes // Propagate theme changes to contained headers internal void OnThemeChanged() { if (Header != null) { DependencyObject d = Header as DependencyObject; if (d != null) { FrameworkElement fe; FrameworkContentElement fce; Helper.DowncastToFEorFCE(d, out fe, out fce, false); if (fe != null || fce != null) { TreeWalkHelper.InvalidateOnResourcesChange(fe, fce, ResourcesChangeInfo.ThemeChangeInfo); } } } } ////// ensure final column width is no less than a value /// internal double EnsureWidth(double width) { if (width > DesiredWidth) { DesiredWidth = width; } return DesiredWidth; } ////// column collection should call this when remove a column from the collection. /// internal void ResetPrivateData() { _actualIndex = -1; _desiredWidth = 0.0; _state = Double.IsNaN(Width) ? ColumnMeasureState.Init : ColumnMeasureState.SpecificWidth; } #endregion //------------------------------------------------------------------- // // Internal Properties // //-------------------------------------------------------------------- #region Internal Properties ////// Reachable State Transition Diagram: /// /// +- - - - - - - - - - + /// | Init | /// +- - - - - - - - - - + /// / /| A |\ \ /// / / | \ \ /// / / | \ \ /// / / | \ \ /// / / | \ \ /// / / | \ \ /// / / | \ \ /// |/ / | \ \| /// +--------------------+ | +--------------------+ /// | Headered |--------+------->| Data | /// +--------------------+ | +--------------------+ /// \ | / /// \ | / /// \ | / /// \ | / /// \ | / /// \ | / /// \| | |/ /// +--------------------+ /// | SpecificWidth | /// +--------------------+ /// /// Note: /// /// 1) Init is a intermidiated state, that is a column should not stop on such a state; /// 2) Headered, Data and SpecificWidth are terminal state, that is a column can stop at /// the state if no further data change / user interaction to trigger a change. /// /// Typical state transiton flows: /// /// Case 1: column is auto, LV has header and data /// Init --> [ Headered --> ] Data /// /// Case 2: column is auto, LV has header but no data /// Init --> Headered /// /// Case 3: column has a specified width /// SpecificWidth /// /// Case 4: couble click a column of case 3 /// SpecificWidth --> Init --> Headered / Data (depends on the data) /// /// Case 5: resize a column which has width as auto /// Headered / Data --> SpecificWidth /// /// internal ColumnMeasureState State { get { return _state; } set { if (_state != value) { _state = value; if (value != ColumnMeasureState.Init) // Headered, Data or SpecificWidth { UpdateActualWidth(); } else { DesiredWidth = 0.0; } } else if (value == ColumnMeasureState.SpecificWidth) { UpdateActualWidth(); } } } // NOTE: Perf optimization. To avoid re-search index again and again // by every GridViewRowPresenter, add an index here. internal int ActualIndex { get { return _actualIndex; } set { _actualIndex = value; } } ////// Minimum width requirement for this column. Shared by all visible cells in this column /// ////// Below table shows an example of how column width is shared: /// /// 1. In the first round of layout, DesiredWidth continue to grow when each row comes into measure /// /// 2. after the 1st round, the desired width for this column is decided, each row on layout updated /// with check this value with its copy of maxDesiredWidth, if not equal, triger another round of /// measure. /// /// 3. after 2nd round of layout, all rows should be in same size. /// +------------+-----------+--------------+------------+------------+-------------+ /// | | Width | Cell | Desired | Presenter | Column | /// | | | DesiredWidth | Width | LocalCopy | State | /// |------------+-----------+--------------+------------+------------|-------------| /// | 1st round | NaN | | 10.0 | | Init | /// | | | | | | | /// | (row 1) | | 12.0 | 12.0 | | | /// | (row 2) | | 70.0 | 70.0 | | | /// | (row 3) | | 80.0 | 80.0 | | | /// | (row 4) | | 60.0 | 80.0 | | | /// |------------+-----------+--------------+------------+------------|-------------| /// | layout | NaN | | | | | /// | updated | | | | | | /// | | | | | | | /// | [hdr_row] | | | | | [Headered]* | /// | | | | | | | /// | (row 1) | | | 80.0 | 12.0 | Data | /// | (row 2) | | | 80.0 | 70.0 | | /// | (row 3) | | | 80.0 | 80.0 | | /// | (row 4) | | | 80.0 | 80.0 | | /// |------------+-----------+--------------+------------+------------|-------------| /// | 2nd round | NaN | | | | | /// | | | | | | | /// | (row 1) | | 12.0 | 80.0 | 80.0 | | /// | (row 2) | | 70.0 | 80.0 | 80.0 | | /// +------------+-----------+--------------+------------+------------+-------------+ /// /// * Depends on the tree structure, it is possible that HeaderRowPresenter accomplish first /// layout first. So the column state can be Headered for a while. But will be changed to /// 'Data' once a data row accomplish its first layout. /// /// internal double DesiredWidth { get { return _desiredWidth; } private set { _desiredWidth = value; } } internal const string c_ActualWidthName = "ActualWidth"; #endregion #region InheritanceContext ////// InheritanceContext /// internal override DependencyObject InheritanceContext { get { return _inheritanceContext; } } // Receive a new inheritance context internal override void AddInheritanceContext(DependencyObject context, DependencyProperty property) { // reinforce that no one can compete to be mentor of this element. if (_inheritanceContext == null && context != null) { // Pick up the new context _inheritanceContext = context; OnInheritanceContextChanged(EventArgs.Empty); } } // Remove an inheritance context internal override void RemoveInheritanceContext(DependencyObject context, DependencyProperty property) { if (_inheritanceContext == context) { // clear the context _inheritanceContext = null; OnInheritanceContextChanged(EventArgs.Empty); } } // Fields to implement DO's inheritance context DependencyObject _inheritanceContext; #endregion InheritanceContext //------------------------------------------------------------------- // // Private Methods / Fields // //-------------------------------------------------------------------- #region Private Methods ////// Helper to raise INotifyPropertyChanged.PropertyChanged event /// /// Name of the changed property private void OnPropertyChanged(string propertyName) { OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); } ////// force ActualWidth to be reevaluated /// private void UpdateActualWidth() { ActualWidth = (State == ColumnMeasureState.SpecificWidth) ? Width : DesiredWidth; } #endregion #region Private Fields private double _desiredWidth; private int _actualIndex; private double _actualWidth; private ColumnMeasureState _state; #endregion } ////// States of column when doing layout /// See GridViewColumn.State for reachable state transition diagram /// internal enum ColumnMeasureState { ////// Column width is just initialized and will size to content width /// Init = 0, ////// Column width reach max desired width of header(s) in this column /// Headered = 1, ////// Column width reach max desired width of data row(s) in this column /// Data = 2, ////// Column has a specific value as width /// SpecificWidth = 3 } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SequentialUshortCollection.cs
- TileModeValidation.cs
- SchemaType.cs
- ISessionStateStore.cs
- AppDomainManager.cs
- FileUtil.cs
- FacetDescriptionElement.cs
- KeyValueSerializer.cs
- DeclarationUpdate.cs
- DataException.cs
- ToolStripPanelCell.cs
- ServicePointManagerElement.cs
- ResourceFallbackManager.cs
- DataGrid.cs
- ListControl.cs
- LogWriteRestartAreaAsyncResult.cs
- XamlPoint3DCollectionSerializer.cs
- CriticalFinalizerObject.cs
- CacheDict.cs
- OciLobLocator.cs
- NamedObject.cs
- DataServiceQueryProvider.cs
- HttpStaticObjectsCollectionWrapper.cs
- WindowsListViewGroupHelper.cs
- Point4DValueSerializer.cs
- ContextMarshalException.cs
- MethodBuilder.cs
- TrackBar.cs
- SoapInteropTypes.cs
- CompleteWizardStep.cs
- ZipIOExtraFieldPaddingElement.cs
- XmlSchemaProviderAttribute.cs
- IndentTextWriter.cs
- Grammar.cs
- SystemWebExtensionsSectionGroup.cs
- IsolatedStorageFileStream.cs
- MimeTypeAttribute.cs
- Native.cs
- ColumnWidthChangingEvent.cs
- DefaultDialogButtons.cs
- Propagator.ExtentPlaceholderCreator.cs
- GeometryConverter.cs
- TextRunProperties.cs
- XmlUrlEditor.cs
- DrawingImage.cs
- OdbcDataAdapter.cs
- RowToFieldTransformer.cs
- FillRuleValidation.cs
- StringValueConverter.cs
- DataControlReferenceCollection.cs
- Completion.cs
- safemediahandle.cs
- SqlReorderer.cs
- ProjectionPruner.cs
- QilXmlReader.cs
- PrimarySelectionAdorner.cs
- DuplicateWaitObjectException.cs
- COM2PropertyBuilderUITypeEditor.cs
- BaseCollection.cs
- VirtualizingPanel.cs
- RSAPKCS1SignatureDeformatter.cs
- DynamicControlParameter.cs
- EntityDataSourceWrapperCollection.cs
- DocumentXmlWriter.cs
- TreeBuilderBamlTranslator.cs
- HotSpotCollection.cs
- MessageDescription.cs
- HostingPreferredMapPath.cs
- ImageSourceValueSerializer.cs
- MethodImplAttribute.cs
- NameScope.cs
- ScaleTransform3D.cs
- FeatureSupport.cs
- HtmlInputRadioButton.cs
- ECDiffieHellman.cs
- _NegoState.cs
- HtmlTableRowCollection.cs
- SingleSelectRootGridEntry.cs
- SignatureDescription.cs
- WebServiceMethodData.cs
- TextEvent.cs
- FrameworkContentElement.cs
- SortableBindingList.cs
- JsonReader.cs
- DesignerActionKeyboardBehavior.cs
- RootProjectionNode.cs
- PropertyNames.cs
- PageWrapper.cs
- TargetControlTypeCache.cs
- DbConvert.cs
- ObjectComplexPropertyMapping.cs
- NeutralResourcesLanguageAttribute.cs
- DesignerProperties.cs
- DataGridViewComboBoxColumn.cs
- RootBrowserWindow.cs
- GridItemPattern.cs
- DataGridViewDataErrorEventArgs.cs
- XmlConvert.cs
- TextRangeSerialization.cs
- EventSchemaTraceListener.cs