GridViewColumn.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / Controls / GridViewColumn.cs / 1 / 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-sync 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
        /// 
        ///         GridViewColumn column = new GridViewColumn();
        ///         column.Header = "Name"; 
        /// 
        /// or 
        ///  
        ///         GridViewColumnHeader header = new GridViewColumnHeader();
        ///         header.Content = "Name"; 
        ///         header.Click += ...
        ///         ...
        ///         GridViewColumn column = new GridViewColumn();
        ///         column.Header = header; 
        /// 
        ///  
        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
 
        /// 
        /// 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  is set.
        ///  
        [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 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; 
        }
 
        #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

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK