GridViewHeaderRowPresenter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / GridViewHeaderRowPresenter.cs / 1305600 / GridViewHeaderRowPresenter.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
//--------------------------------------------------------------------------- 

 
using System.Collections.Generic;           // List 
using System.Collections.Specialized;       // NotifyCollectionChangedAction
using System.ComponentModel;                // DesignerSerializationVisibility 
using System.Windows.Automation.Peers;      // AutomationPeer
using System.Windows.Controls.Primitives;   // GridViewRowPresenterBase
using System.Windows.Data;                  // Binding
using System.Windows.Input;                 // MouseEventArgs 
using System.Windows.Media;                 // SolidColorBrush
using System.Diagnostics; 
 
using MS.Internal;                          // Helper
 

namespace System.Windows.Controls
{
    ///  
    /// GridViewHeaderRowPresenter is used within the style to denote the headers place
    /// in GridView's visual tree 
    ///  
    [StyleTypedProperty(Property = "ColumnHeaderContainerStyle", StyleTargetType = typeof(GridViewColumnHeader))]
    public class GridViewHeaderRowPresenter : GridViewRowPresenterBase 
    {
        //-------------------------------------------------------------------
        //
        //  Constructors 
        //
        //------------------------------------------------------------------- 
 
        //--------------------------------------------------------------------
        // 
        //  Public Methods
        //
        //-------------------------------------------------------------------
 
        //--------------------------------------------------------------------
        // 
        //  Public Properties 
        //
        //-------------------------------------------------------------------- 

        #region Public Properties

        #region ColumnHeaderContainerStyle 

        ///  
        /// ColumnHeaderContainerStyleProperty DependencyProperty 
        /// 
        public static readonly DependencyProperty ColumnHeaderContainerStyleProperty = 
                GridView.ColumnHeaderContainerStyleProperty.AddOwner(
                    typeof(GridViewHeaderRowPresenter),
                    new FrameworkPropertyMetadata(
                        new PropertyChangedCallback(PropertyChanged)) 
                    );
 
        ///  
        /// header container's style
        ///  
        public Style ColumnHeaderContainerStyle
        {
            get { return (Style)GetValue(ColumnHeaderContainerStyleProperty); }
            set { SetValue(ColumnHeaderContainerStyleProperty, value); } 
        }
 
        #endregion // ColumnHeaderContainerStyle 

        #region ColumnHeaderTemplate 

        /// 
        /// ColumnHeaderTemplate DependencyProperty
        ///  
        public static readonly DependencyProperty ColumnHeaderTemplateProperty =
            GridView.ColumnHeaderTemplateProperty.AddOwner( 
                typeof(GridViewHeaderRowPresenter), 
                new FrameworkPropertyMetadata(
                    new PropertyChangedCallback(PropertyChanged)) 
            );

        /// 
        /// column header template 
        /// 
        public DataTemplate ColumnHeaderTemplate 
        { 
            get { return (DataTemplate)GetValue(ColumnHeaderTemplateProperty); }
            set { SetValue(ColumnHeaderTemplateProperty, value); } 
        }

        #endregion  ColumnHeaderTemplate
 
        #region ColumnHeaderTemplateSelector
 
        ///  
        /// ColumnHeaderTemplateSelector DependencyProperty
        ///  
        public static readonly DependencyProperty ColumnHeaderTemplateSelectorProperty =
            GridView.ColumnHeaderTemplateSelectorProperty.AddOwner(
                typeof(GridViewHeaderRowPresenter),
                new FrameworkPropertyMetadata( 
                    new PropertyChangedCallback(PropertyChanged))
            ); 
 
        /// 
        /// header template selector 
        /// 
        /// 
        ///     This property is ignored if  is set.
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public DataTemplateSelector ColumnHeaderTemplateSelector 
        { 
            get { return (DataTemplateSelector)GetValue(ColumnHeaderTemplateSelectorProperty); }
            set { SetValue(ColumnHeaderTemplateSelectorProperty, value); } 
        }

        #endregion ColumnHeaderTemplateSelector
 
        #region ColumnHeaderStringFormat
 
        ///  
        /// ColumnHeaderStringFormat DependencyProperty
        ///  
        public static readonly DependencyProperty ColumnHeaderStringFormatProperty =
            GridView.ColumnHeaderStringFormatProperty.AddOwner(
                typeof(GridViewHeaderRowPresenter),
                new FrameworkPropertyMetadata( 
                    new PropertyChangedCallback(PropertyChanged))
            ); 
 
        /// 
        /// header template selector 
        /// 
        /// 
        ///     This property is ignored if  is set.
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public String ColumnHeaderStringFormat 
        { 
            get { return (String)GetValue(ColumnHeaderStringFormatProperty); }
            set { SetValue(ColumnHeaderStringFormatProperty, value); } 
        }

        #endregion ColumnHeaderStringFormat
 
        #region AllowsColumnReorder
 
        ///  
        /// AllowsColumnReorder DependencyProperty
        ///  
        public static readonly DependencyProperty AllowsColumnReorderProperty =
            GridView.AllowsColumnReorderProperty.AddOwner(
                typeof(GridViewHeaderRowPresenter)
            ); 

        ///  
        /// Allow column re-order or not 
        /// 
        public bool AllowsColumnReorder 
        {
            get { return (bool)GetValue(AllowsColumnReorderProperty); }
            set { SetValue(AllowsColumnReorderProperty, value); }
        } 

        #endregion  AllowsColumnReorder 
 
        #region ColumnHeaderContextMenu
 
        /// 
        /// ColumnHeaderContextMenu DependencyProperty
        /// 
        public static readonly DependencyProperty ColumnHeaderContextMenuProperty = 
            GridView.ColumnHeaderContextMenuProperty.AddOwner(
                typeof(GridViewHeaderRowPresenter), 
                new FrameworkPropertyMetadata( 
                    new PropertyChangedCallback(PropertyChanged))
            ); 

        /// 
        /// ColumnHeaderContextMenu
        ///  
        public ContextMenu ColumnHeaderContextMenu
        { 
            get { return (ContextMenu)GetValue(ColumnHeaderContextMenuProperty); } 
            set { SetValue(ColumnHeaderContextMenuProperty, value); }
        } 

        #endregion  ColumnHeaderContextMenu

        #region ColumnHeaderToolTip 

        ///  
        /// ColumnHeaderToolTip DependencyProperty 
        /// 
        public static readonly DependencyProperty ColumnHeaderToolTipProperty = 
            GridView.ColumnHeaderToolTipProperty.AddOwner(
                typeof(GridViewHeaderRowPresenter),
                new FrameworkPropertyMetadata(
                    new PropertyChangedCallback(PropertyChanged)) 
            );
 
        ///  
        /// ColumnHeaderToolTip
        ///  
        public object ColumnHeaderToolTip
        {
            get { return GetValue(ColumnHeaderToolTipProperty); }
            set { SetValue(ColumnHeaderToolTipProperty, value); } 
        }
 
        private static void PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            GridViewHeaderRowPresenter presenter = (GridViewHeaderRowPresenter)d; 

            if (e.Property == ColumnHeaderTemplateProperty || e.Property == ColumnHeaderTemplateSelectorProperty)
            {
                // Check to prevent Template and TemplateSelector at the same time 
                Helper.CheckTemplateAndTemplateSelector("GridViewHeaderRowPresenter", ColumnHeaderTemplateProperty, ColumnHeaderTemplateSelectorProperty, presenter);
            } 
 
            presenter.UpdateAllHeaders(e.Property);
        } 

        #endregion  ColumnHeaderToolTip

        #endregion 

        //------------------------------------------------------------------- 
        // 
        // Protected Methods
        // 
        //--------------------------------------------------------------------

        #region Protected Methods
 
        /// 
        /// Override of . 
        ///  
        /// Constraint size is an "upper limit" that the return value should not exceed.
        /// The GridViewHeaderRowPresenter's desired size. 
        protected override Size MeasureOverride(Size constraint)
        {
            GridViewColumnCollection columns = Columns;
 
            UIElementCollection children = InternalChildren;
 
            double maxHeight = 0.0;           // Max height of children. 
            double accumulatedWidth = 0.0;    // Total width consumed by children.
            double constraintHeight = constraint.Height; 
            bool desiredWidthListEnsured = false;

            if (columns != null)
            { 
                // Measure working headers
                for (int i = 0; i < columns.Count; ++i) 
                { 
                    UIElement child = children[GetVisualIndex(i)];
                    if (child == null) { continue; } 

                    double childConstraintWidth = Math.Max(0.0, constraint.Width - accumulatedWidth);

                    GridViewColumn column = columns[i]; 

                    if (column.State == ColumnMeasureState.Init) 
                    { 
                        if (!desiredWidthListEnsured)
                        { 
                            EnsureDesiredWidthList();
                            LayoutUpdated += new EventHandler(OnLayoutUpdated);
                            desiredWidthListEnsured = true;
                        } 

                        child.Measure(new Size(childConstraintWidth, constraintHeight)); 
 
                        DesiredWidthList[column.ActualIndex] = column.EnsureWidth(child.DesiredSize.Width);
 
                        accumulatedWidth += column.DesiredWidth;
                    }
                    else if (column.State == ColumnMeasureState.Headered
                        || column.State == ColumnMeasureState.Data) 
                    {
                        childConstraintWidth = Math.Min(childConstraintWidth, column.DesiredWidth); 
 
                        child.Measure(new Size(childConstraintWidth, constraintHeight));
 
                        accumulatedWidth += column.DesiredWidth;
                    }
                    else // ColumnMeasureState.SpecificWidth
                    { 
                        childConstraintWidth = Math.Min(childConstraintWidth, column.Width);
 
                        child.Measure(new Size(childConstraintWidth, constraintHeight)); 

                        accumulatedWidth += column.Width; 
                    }

                    maxHeight = Math.Max(maxHeight, child.DesiredSize.Height);
                } 
            }
 
            // Measure padding header 
            Debug.Assert(_paddingHeader != null, "padding header is null");
            _paddingHeader.Measure(new Size(0.0, constraintHeight)); 
            maxHeight = Math.Max(maxHeight, _paddingHeader.DesiredSize.Height);

            // reserve space for padding header next to the last column
            accumulatedWidth += c_PaddingHeaderMinWidth; 

            // Measure indicator & floating header in re-ordering 
            if (_isHeaderDragging) 
            {
                Debug.Assert(_indicator != null, "_indicator is null"); 
                Debug.Assert(_floatingHeader != null, "_floatingHeader is null");

                // Measure indicator
                _indicator.Measure(constraint); 

                // Measure floating header 
                _floatingHeader.Measure(constraint); 
            }
 
            return (new Size(accumulatedWidth, maxHeight));
        }

        ///  
        /// GridViewHeaderRowPresenter computes the position of its children inside each child's Margin and calls Arrange
        /// on each child. 
        ///  
        /// Size the GridViewHeaderRowPresenter will assume.
        protected override Size ArrangeOverride(Size arrangeSize) 
        {
            GridViewColumnCollection columns = Columns;

            UIElementCollection children = InternalChildren; 

            double accumulatedWidth = 0.0; 
            double remainingWidth = arrangeSize.Width; 
            Rect rect;
 
            HeadersPositionList.Clear();

            if (columns != null)
            { 
                // Arrange working headers
                for (int i = 0; i < columns.Count; ++i) 
                { 
                    UIElement child = children[GetVisualIndex(i)];
                    if (child == null) { continue; } 

                    GridViewColumn column = columns[i];

                    // has a given value or 'auto' 
                    double childArrangeWidth = Math.Min(remainingWidth, ((column.State == ColumnMeasureState.SpecificWidth) ? column.Width : column.DesiredWidth));
 
                    // calculate the header rect 
                    rect = new Rect(accumulatedWidth, 0.0, childArrangeWidth, arrangeSize.Height);
 
                    // arrange header
                    child.Arrange(rect);

                    //Store rect in HeadersPositionList as i-th column position 
                    HeadersPositionList.Add(rect);
 
                    remainingWidth -= childArrangeWidth; 
                    accumulatedWidth += childArrangeWidth;
                } 

                // check width to hide previous header's right half gripper, from the first working header to padding header
                // only happens after column delete, insert, move
                if (_isColumnChangedOrCreated) 
                {
                    for (int i = 0; i < columns.Count; ++i) 
                    { 
                        GridViewColumnHeader header = children[GetVisualIndex(i)] as GridViewColumnHeader;
 
                        header.CheckWidthForPreviousHeaderGripper();
                    }

                    _paddingHeader.CheckWidthForPreviousHeaderGripper(); 

                    _isColumnChangedOrCreated = false; 
                } 
            }
 
            // Arrange padding header
            Debug.Assert(_paddingHeader != null, "padding header is null");
            rect = new Rect(accumulatedWidth, 0.0, Math.Max(remainingWidth, 0.0), arrangeSize.Height);
            _paddingHeader.Arrange(rect); 
            HeadersPositionList.Add(rect);
 
            // if re-order started, arrange floating header & indicator 
            if (_isHeaderDragging)
            { 
                _floatingHeader.Arrange(new Rect(new Point(_currentPos.X - _relativeStartPos.X, 0), HeadersPositionList[_startColumnIndex].Size));

                Point pos = FindPositionByIndex(_desColumnIndex);
                _indicator.Arrange(new Rect(pos, new Size(_indicator.DesiredSize.Width, arrangeSize.Height))); 
            }
 
            return arrangeSize; 
        }
 
        /// 
        /// This is the method that responds to the MouseButtonEvent event.
        /// 
        /// Event arguments 
        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        { 
            GridViewColumnHeader header = e.Source as GridViewColumnHeader; 

            if (header != null && AllowsColumnReorder) 
            {
                PrepareHeaderDrag(header, e.GetPosition(this), e.GetPosition(header), false);

                MakeParentItemsControlGotFocus(); 
            }
 
            e.Handled = true; 

            base.OnMouseLeftButtonDown(e); 
        }

        /// 
        /// This is the method that responds to the MouseButtonEvent event. 
        /// 
        /// Event arguments 
        protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) 
        {
            // Important to clean the prepare dragging state 
            _prepareDragging = false;

            if (_isHeaderDragging)
            { 
                FinishHeaderDrag(false);
            } 
 
            e.Handled = true;
 
            base.OnMouseLeftButtonUp(e);
        }

        ///  
        /// This is the method that responds to the MouseEvent event.
        ///  
        /// Event arguments 
        protected override void OnMouseMove(MouseEventArgs e)
        { 
            base.OnMouseMove(e);

            if (e.LeftButton == MouseButtonState.Pressed)
            { 
                // if prepare re-order or already re-order
                if (_prepareDragging) 
                { 
                    Debug.Assert(_draggingSrcHeader != null, "_draggingSrcHeader is null");
 
                    _currentPos = e.GetPosition(this);
                    _desColumnIndex = FindIndexByPosition(_currentPos, true);

                    if (!_isHeaderDragging) 
                    {
                        // Re-order begins only if horizontal move exceeds threshold 
                        if (CheckStartHeaderDrag(_currentPos, _startPos)) 
                        {
                            // header dragging start 
                            StartHeaderDrag();

                            // need to measure indicator because floating header is updated
                            InvalidateMeasure(); 
                        }
                    } 
                    else // NOTE: Not-Dragging/Dragging should be divided into two stages in MouseMove 
                    {
                        // Check floating & indicator visibility 
                        // Display floating header if vertical move not exceeds header.Height * 2
                        bool isDisplayingFloatingHeader = IsMousePositionValid(_floatingHeader, _currentPos, 2.0);

                        // floating header and indicator are visibile/invisible at the same time 
                        _indicator.Visibility = _floatingHeader.Visibility = isDisplayingFloatingHeader ? Visibility.Visible : Visibility.Hidden;
 
                        InvalidateArrange(); 
                    }
                } 
            }

            e.Handled = true;
        } 

        ///  
        /// Cancel header dragging if we lost capture 
        /// 
        ///  
        protected override void OnLostMouseCapture(MouseEventArgs e)
        {
            base.OnLostMouseCapture(e);
 
            // OnLostMouseCapture is invoked before OnMouseLeftButtonUp, so we need to distinguish
            // the cause of capture lose 
            //      if LeftButton is pressed when lost mouse capture, we treat it as cancel 
            //      Because GridViewHeaderRowPresenter never capture Mouse (GridViewColumnHeader did this),
            //      the Mouse.Captured is always null 
            if (e.LeftButton == MouseButtonState.Pressed && _isHeaderDragging)
            {
                FinishHeaderDrag(true);
            } 

            // Important to clean the prepare dragging state 
            _prepareDragging = false; 
        }
 
        #endregion Protected Methods

        //-------------------------------------------------------------------
        // 
        // Internal Methods
        // 
        //------------------------------------------------------------------- 

        #region Internal Methods 

        /// 
        /// create the headers tree
        ///  
        internal override void OnPreApplyTemplate()
        { 
            //  +-- GridViewHeaderRowPresenter ----------------------------+ 
            //  |                                                          |
            //  |  +- Header1 ---+ +- Header2 ---+ +- PaddingHeader -+     | 
            //  |  |         +--------+      +--------+            |       |
            //  |  |         +Gripper +      +Gripper +            |  ...  |
            //  |  |         +--------+      +--------+            |       |
            //  |  +-------------+ +-------------+ +---------------+       | 
            //  +---------------------------------------------------------+
 
            // 
            //  Given a column collection with 3 columns
            // 
            //      { A, B, C },
            //
            //  Visually, GridViewHeaderRowPresenter will them present as:
            // 
            //      { A, B, C, Padding }
            // 
            //  If in Reorder-Mode, there will be 2 more be visible: 
            //
            //      { A, [Indctr],     B,      C,    Padding    } 
            //      {           [-- Float --]                 }
            //
            //  And internally the visual child collection is in order of:
            // 
            //      { Padding, C, B, A, Indicator, Float}
            // 
            //  Method GetVisualIndex() is for coverting a Columns based 
            //  index to visual child collection based index.
            // 
            //  E.g., Columns based index of column A is 0, while
            //  and it lives 3rd in the visual collection, so
            //
            //      GetVisualIndex(0) = 3. 
            //
 
            base.OnPreApplyTemplate(); 

            if (NeedUpdateVisualTree) 
            {
                // build the whole collection from draft.

                // IMPORTANT! 
                // The correct sequence to build the VisualTree in Z-order:
                // 1. Padding header 
                // 2. The working Column header (if any) 
                // 3. Indicator
                // 4. Floating header 
                //

                UIElementCollection children = InternalChildren;
                GridViewColumnCollection columns = Columns; 

                // renew ScrollViewer, ScrollChanged event, ItemsControl and KeyDown event 
                RenewEvents(); 

                if (children.Count == 0) 
                {
                    // Build and add the padding header, even if no GridViewColumn is defined
                    AddPaddingColumnHeader();
 
                    // Create and add indicator
                    AddIndicator(); 
 
                    // Create and add floating header
                    AddFloatingHeader(null); 
                }
                else if (children.Count > 3)
                {
                    // clear column headers left from last view. 
                    int count = children.Count - 3;
                    for (int i = 0; i < count; i++) 
                    { 
                        RemoveHeader(null, 1);
                    } 
                }

                UpdatePaddingHeader(_paddingHeader);
 
                //
                // Build the column header. 
                // The interesting thing is headers must be built from right to left, 
                // in order to make the left header's gripper overlay the right header
                // 
                if (columns != null)
                {
                    int visualIndex = 1;
 
                    for (int columnIndex = columns.Count - 1; columnIndex >= 0; columnIndex--)
                    { 
                        GridViewColumn column = columns[columnIndex]; 

                        GridViewColumnHeader header = CreateAndInsertHeader(column, visualIndex++); 
                    }
                }

                // Link headers 
                BuildHeaderLinks();
 
                NeedUpdateVisualTree = false; 

                _isColumnChangedOrCreated = true; 
            }
        }

        ///  
        /// Override column's PropertyChanged event handler. Update  correspondent
        /// property if change is of Width / Header / 
        /// HeaderContainerStyle / Template / Selector. 
        /// 
        internal override void OnColumnPropertyChanged(GridViewColumn column, string propertyName) 
        {
            Debug.Assert(column != null);
            if (column.ActualIndex >= 0)
            { 
                GridViewColumnHeader header = FindHeaderByColumn(column);
                if (header != null) 
                { 
                    if (GridViewColumn.WidthProperty.Name.Equals(propertyName)
                        || GridViewColumn.c_ActualWidthName.Equals(propertyName)) 
                    {
                        InvalidateMeasure();
                    }
                    else if (GridViewColumn.HeaderProperty.Name.Equals(propertyName)) 
                    {
                        if (!header.IsInternalGenerated /* the old header is its own container */ 
                            || column.Header is GridViewColumnHeader /* the new header is its own container */) 
                        {
                            // keep the header index in Children collection 
                            int i = InternalChildren.IndexOf(header);

                            // Remove the old header
                            RemoveHeader(header, -1); 

                            // Insert a (the) new header 
                            GridViewColumnHeader newHeader = CreateAndInsertHeader(column, i); 

                            // Link headers 
                            BuildHeaderLinks();
                        }
                        else
                        { 
                            UpdateHeaderContent(header);
                        } 
                    } 
                    else
                    { 
                        DependencyProperty columnDP = GetColumnDPFromName(propertyName);

                        if (columnDP != null)
                        { 
                            UpdateHeaderProperty(header, columnDP);
                        } 
                    } 
                }
            } 
        }

        internal override void OnColumnCollectionChanged(GridViewColumnCollectionChangedEventArgs e)
        { 
            base.OnColumnCollectionChanged(e);
 
            int index; 
            GridViewColumnHeader header;
            UIElementCollection children = InternalChildren; 
            GridViewColumn column;

            switch (e.Action)
            { 
                case NotifyCollectionChangedAction.Move:
                    int start = GetVisualIndex(e.OldStartingIndex); 
                    int end = GetVisualIndex(e.NewStartingIndex); 

                    header = (GridViewColumnHeader)children[start]; 
                    children.RemoveAt(start);
                    children.InsertInternal(end, header);

                    break; 

                case NotifyCollectionChangedAction.Add: 
                    index = GetVisualIndex(e.NewStartingIndex); 
                    column = (GridViewColumn)(e.NewItems[0]);
 
                    CreateAndInsertHeader(column, index + 1); // index + 1 because visual index is reversed from column index

                    break;
 
                case NotifyCollectionChangedAction.Remove:
                    RemoveHeader(null, GetVisualIndex(e.OldStartingIndex)); 
 
                    break;
 
                case NotifyCollectionChangedAction.Replace:
                    index = GetVisualIndex(e.OldStartingIndex);
                    RemoveHeader(null, index);
 
                    column = (GridViewColumn)(e.NewItems[0]);
                    CreateAndInsertHeader(column, index); 
 
                    break;
 
                case NotifyCollectionChangedAction.Reset:
                    int count = e.ClearedColumns.Count;
                    for (int i = 0; i < count; i++)
                    { 
                        RemoveHeader(null, 1);
                    } 
 
                    break;
            } 

            // Link headers
            BuildHeaderLinks();
            _isColumnChangedOrCreated = true; 
        }
 
        // Make the parent got focus if it's ItemsControl 
        // make this method internal, so GVCH can call it when header is invoked through access key
        internal void MakeParentItemsControlGotFocus() 
        {
            if (_itemsControl != null && !_itemsControl.IsKeyboardFocusWithin)
            {
                // send focus to item. 
                ListBox parent = _itemsControl as ListBox;
                if (parent != null && parent.LastActionItem != null) 
                { 
                    parent.LastActionItem.Focus();
                } 
                else
                {
                    _itemsControl.Focus();
                } 
            }
        } 
 
        /// 
        /// Refresh a dp of a header. Column is the 1st priority source, GridView 2nd. 
        /// 
        /// the header to update
        /// the DP which trigger this update
        internal void UpdateHeaderProperty(GridViewColumnHeader header, DependencyProperty property) 
        {
            DependencyProperty gvDP, columnDP, headerDP; 
            GetMatchingDPs(property, out gvDP, out columnDP, out headerDP); 

            UpdateHeaderProperty(header, headerDP, columnDP, gvDP); 
        }

        #endregion Internal Methods
 
        //--------------------------------------------------------------------
        // 
        //  Accessibility 
        //
        //------------------------------------------------------------------- 

        #region Accessibility

        ///  
        /// Creates AutomationPeer ()
        ///  
        protected override AutomationPeer OnCreateAutomationPeer() 
        {
            return new GridViewHeaderRowPresenterAutomationPeer(this); 
        }

        #endregion
 
        //--------------------------------------------------------------------
        // 
        // Private Methods 
        //
        //-------------------------------------------------------------------- 

        #region Private Methods

        private void OnLayoutUpdated(object sender, EventArgs e) 
        {
            bool desiredWidthChanged = false; // whether the shared minimum width has been changed since last layout 
 
            foreach (GridViewColumn column in Columns)
            { 
                if ((column.State != ColumnMeasureState.SpecificWidth))
                {
                    if (column.State == ColumnMeasureState.Init)
                    { 
                        column.State = ColumnMeasureState.Headered;
                    } 
 
                    if (DesiredWidthList == null || column.ActualIndex >= DesiredWidthList.Count)
                    { 
                        // How can this happen?
                        // Between the last measure was called and this update is called, there can be a
                        // change done to the ColumnCollection and result in DesiredWidthList out of [....]
                        // with the columnn collection. What can we do is end this call asap and the next 
                        // measure will fix it.
                        desiredWidthChanged = true; 
                        break; 
                    }
 
                    if (!DoubleUtil.AreClose(column.DesiredWidth, DesiredWidthList[column.ActualIndex]))
                    {
                        // Update the record because collection operation latter on might
                        // need to verified this list again, e.g. insert an 'auto' 
                        // column, so that we won't trigger unnecessary update due to
                        // inconsistency of this column. 
                        DesiredWidthList[column.ActualIndex] = column.DesiredWidth; 

                        desiredWidthChanged = true; 
                    }
                }
            }
 
            if (desiredWidthChanged)
            { 
                InvalidateMeasure(); 
            }
 
            LayoutUpdated -= new EventHandler(OnLayoutUpdated);
        }

        // Map column collection index to header collection index in visual tree 
        private int GetVisualIndex(int columnIndex)
        { 
            // Elements in visual tree: working headers, padding header, indicator, and floating header 
            int index = InternalChildren.Count - 3 - columnIndex;
            Debug.Assert(index >= 0 && index < InternalChildren.Count, "Error index when GetVisualIndex"); 

            return index;
        }
 
        // Link headers from right to left
        private void BuildHeaderLinks() 
        { 
            GridViewColumnHeader lastHeader = null;
 
            if (Columns != null)
            {
                // link working headers.
                for (int i = 0; i < Columns.Count; i++) 
                {
                    GridViewColumnHeader header = (GridViewColumnHeader)InternalChildren[GetVisualIndex(i)]; 
                    header.PreviousVisualHeader = lastHeader; 
                    lastHeader = header;
                } 
            }

            // link padding header to last header
            if (_paddingHeader != null) 
            {
                _paddingHeader.PreviousVisualHeader = lastHeader; 
            } 
        }
 
        //
        // This method will do following tasks:
        //  1. Disconnect header from visual parent and logical parent, if any.
        //  2. Create a new header or use the header directly if the GridViewColumn.Header property 
        //      is qualify for its own container;
        //  3. Insert the header in the InternalChildren collection 
        //  4. Perform routine update and hookup jobs 
        //
        private GridViewColumnHeader CreateAndInsertHeader(GridViewColumn column, int index) 
        {
            object header = column.Header;
            GridViewColumnHeader headerContainer = header as GridViewColumnHeader;
 
            //
            // NOTE: when theme chagned, all properties, templates and styles will be reevaluated. 
            // But there are 2 cases we need to handle: 
            //
            //  1: header property is a qualified container for itself 
            //    
            //        
            //    
            // 
            //  2: header property is a Visual element
            //     
            //        

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