GridViewRowPresenterBase.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 / Primitives / GridViewRowPresenterBase.cs / 1 / GridViewRowPresenterBase.cs

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

 
using System.Collections;               // IEnumerator 
using System.Collections.Generic;       // List
using System.Collections.Specialized;   // NotifyCollectionChangedEventHandler 
using System.Collections.ObjectModel;   // Collection
using System.ComponentModel;            // PropertyChangedEventArgs
using System.Diagnostics;               // Debug
using System.Windows.Media;             // VisualOperations 

using MS.Internal.Controls;             // EmptyEnumerator 
 

namespace System.Windows.Controls.Primitives 
{
    /// 
    /// Base class for GridViewfRowPresenter and HeaderRowPresenter.
    ///  
    public abstract class GridViewRowPresenterBase : FrameworkElement, IWeakEventListener
    { 
        //------------------------------------------------------------------- 
        //
        //  Public Methods 
        //
        //-------------------------------------------------------------------

        #region Public Methods 

        ///  
        ///     Returns a string representation of this object. 
        /// 
        ///  
        public override string ToString()
        {
            return SR.Get(SRID.ToStringFormatString_GridViewRowPresenterBase,
                this.GetType(), 
                (Columns != null) ? Columns.Count : 0);
        } 
 
        #endregion
 
        //--------------------------------------------------------------------
        //
        // Public Properties
        // 
        //-------------------------------------------------------------------
 
        #region Public Properties 

        ///  
        ///  Columns DependencyProperty
        /// 
        public static readonly DependencyProperty ColumnsProperty =
            DependencyProperty.Register( 
                "Columns",
                typeof(GridViewColumnCollection), 
                typeof(GridViewRowPresenterBase), 
                new FrameworkPropertyMetadata(
                    (GridViewColumnCollection)null /* default value */, 
                    FrameworkPropertyMetadataOptions.AffectsMeasure,
                    new PropertyChangedCallback(ColumnsPropertyChanged))
            );
 
        /// 
        /// Columns Property 
        ///  
        public GridViewColumnCollection Columns
        { 
            get { return (GridViewColumnCollection)GetValue(ColumnsProperty); }
            set { SetValue(ColumnsProperty, value); }
        }
 
        #endregion
 
        //-------------------------------------------------------------------- 
        //
        // Protected Methods / Properties 
        //
        //--------------------------------------------------------------------

        #region Protected Methods / Properties 

        ///  
        /// Returns enumerator to logical children. 
        /// 
        protected internal override IEnumerator LogicalChildren 
        {
            get
            {
                if (InternalChildren.Count == 0) 
                {
                    // empty GridViewRowPresenterBase has *no* logical children; give empty enumerator 
                    return EmptyEnumerator.Instance; 
                }
 
                // otherwise, its logical children is its visual children
                return InternalChildren.GetEnumerator();
            }
        } 

        ///  
        /// Gets the Visual children count. 
        /// 
        protected override int VisualChildrenCount 
        {
            get
            {
                if (_uiElementCollection == null) 
                {
                    return 0; 
                } 
                else
                { 
                    return _uiElementCollection.Count;
                }
            }
        } 

        ///  
        /// Gets the Visual child at the specified index. 
        /// 
        protected override Visual GetVisualChild(int index) 
        {
            if (_uiElementCollection == null)
            {
                throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange)); 
            }
            return _uiElementCollection[index]; 
        } 

        #endregion 

        //-------------------------------------------------------------------
        //
        // Internal Methods / Properties 
        //
        //-------------------------------------------------------------------- 
 
        #region Internal Methods
 
        /// 
        /// process the column collection chagned event
        /// 
        internal virtual void OnColumnCollectionChanged(GridViewColumnCollectionChangedEventArgs e) 
        {
            if (DesiredWidthList != null) 
            { 
                if (e.Action == NotifyCollectionChangedAction.Remove
                    || e.Action == NotifyCollectionChangedAction.Replace) 
                {
                    // NOTE: The steps to make DesiredWidthList.Count <= e.ActualIndex
                    //
                    //  1. init with 3 auto columns; 
                    //  2. add 1 column to the column collection with width 90.0;
                    //  3. remove the column we jsut added to the the collection; 
                    // 
                    //  Now we have DesiredWidthList.Count equals to 3 while the removed column
                    //  has  ActualIndex equals to 3. 
                    //
                    if (DesiredWidthList.Count > e.ActualIndex)
                    {
                        DesiredWidthList.RemoveAt(e.ActualIndex); 
                    }
                } 
                else if (e.Action == NotifyCollectionChangedAction.Reset) 
                {
                    DesiredWidthList = null; 
                }
            }
        }
 
        /// 
        /// process the column property chagned event 
        ///  
        internal abstract void OnColumnPropertyChanged(GridViewColumn column, string propertyName);
 
        /// 
        /// ensure ShareStateList have at least columns.Count items
        /// 
        internal void EnsureDesiredWidthList() 
        {
            GridViewColumnCollection columns = Columns; 
 
            if (columns != null)
            { 
                int count = columns.Count;

                if (DesiredWidthList == null)
                { 
                    DesiredWidthList = new List(count);
                } 
 
                int c = count - DesiredWidthList.Count;
                for (int i = 0; i < c; i++) 
                {
                    DesiredWidthList.Add(Double.NaN);
                }
            } 
        }
 
        ///  
        /// list of currently reached max value of DesiredWidth of cell in the column
        ///  
        internal List DesiredWidthList
        {
            get { return _desiredWidthList; }
            private set { _desiredWidthList = value; } 
        }
 
        ///  
        /// if visual tree is out of date
        ///  
        internal bool NeedUpdateVisualTree
        {
            get { return _needUpdateVisualTree; }
            set { _needUpdateVisualTree = value; } 
        }
 
        ///  
        /// collection if children
        ///  
        internal UIElementCollection InternalChildren
        {
            get
            { 
                if (_uiElementCollection == null) //nobody used it yet
                { 
                    _uiElementCollection = new UIElementCollection(this /* visual parent */, this /* logical parent */); 
                }
 
                return _uiElementCollection;
            }
        }
 
        // the minimum width for dummy header when measure
        internal const double c_PaddingHeaderMinWidth = 2.0; 
 
        #endregion
 
        //-------------------------------------------------------------------
        //
        // Private Methods / Properties / Fields
        // 
        //-------------------------------------------------------------------
 
        #region Private Methods / Properties / Fields 

        // Property invalidation callback invoked when ColumnCollectionProperty is invalidated 
        private static void ColumnsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            GridViewRowPresenterBase c = (GridViewRowPresenterBase)d;
 
            GridViewColumnCollection oldCollection = (GridViewColumnCollection)e.OldValue;
 
            if (oldCollection != null) 
            {
                InternalCollectionChangedEventManager.RemoveListener(oldCollection, c); 

                // NOTE:
                // If the collection is NOT in view mode (a.k.a owner isn't GridView),
                // RowPresenter is responsible to be or to find one to be the collection's mentor. 
                //
                if (!oldCollection.InViewMode && oldCollection.Owner == c.GetStableAncester()) 
                { 
                    oldCollection.Owner = null;
                } 
            }

            GridViewColumnCollection newCollection = (GridViewColumnCollection)e.NewValue;
 
            if (newCollection != null)
            { 
                InternalCollectionChangedEventManager.AddListener(newCollection, c); 

                // Similar to what we do to oldCollection. But, of course, in a reverse way. 
                if (!newCollection.InViewMode && newCollection.Owner == null)
                {
                    newCollection.Owner = c.GetStableAncester();
                } 
            }
 
            c.NeedUpdateVisualTree = true; 
            c.InvalidateMeasure();
        } 

        //
        // NOTE:
        // 
        // If the collection is NOT in view mode, RowPresenter should be mentor of the Collection.
        // But if presenter + collection are used to restyle ListBoxItems and the ItemsPanel is 
        // VSP, there are 2 problems: 
        //
        //  1. each RowPresenter want to be the mentor, too many context change event 
        //  2. when doing scroll, VSP will dispose those LB items which are out of view. But they
        //      are still referenced by the Collecion (at the Owner property) - memory leak.
        //
        // Solution: 
        //  If RowPresenter is inside an ItemsControl (IC\LB\CB), use the ItemsControl as the
        //  mentor. Therefore, 
        //      - context change is minimized because ItemsControl for different items is the same; 
        //      - no memory leak because when viturlizing, only dispose items not the IC itself.
        // 
        private FrameworkElement GetStableAncester()
        {
            ItemsControl ic = ItemsControl.ItemsControlFromItemContainer(TemplatedParent);
 
            return (ic != null) ? ic : (FrameworkElement)this;
        } 
 
        // if and only if both conditions below are satisfied, row presenter visual is ready.
        // 1. is initialized, which ensures RowPresenter is created 
        // 2. !NeedUpdateVisualTree, which ensures all visual elements generated by RowPresenter are created
        private bool IsPresenterVisualReady
        {
            get { return (IsInitialized && !NeedUpdateVisualTree); } 
        }
 
        ///  
        /// Handle events from the centralized event table
        ///  
        bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs args)
        {
            if (managerType == typeof(InternalCollectionChangedEventManager))
            { 
                ColumnCollectionChanged(sender, (NotifyCollectionChangedEventArgs)args);
            } 
            else 
            {
                return false;       // unrecognized event 
            }

            return true;
        } 

        ///  
        /// Handler of GridViewColumnCollection.CollectionChanged event. 
        /// 
        private void ColumnCollectionChanged(object sender, NotifyCollectionChangedEventArgs arg) 
        {
            GridViewColumnCollectionChangedEventArgs e = arg as GridViewColumnCollectionChangedEventArgs;

            if (e != null 
                && IsPresenterVisualReady)// if and only if rowpresenter's visual is ready, shall rowpresenter go ahead process the event.
            { 
                // Property of one column changed 
                if (e.Column != null)
                { 
                    OnColumnPropertyChanged(e.Column, e.PropertyName);
                }
                else
                { 
                    OnColumnCollectionChanged(e);
                } 
            } 
        }
 
        private UIElementCollection _uiElementCollection;
        private bool _needUpdateVisualTree = true;
        private List _desiredWidthList;
 
        #endregion
    } 
 
    /// 
    /// Manager for the GridViewColumnCollection.CollectionChanged event. 
    /// 
    internal class InternalCollectionChangedEventManager : WeakEventManager
    {
        #region Constructors 

        // 
        //  Constructors 
        //
 
        private InternalCollectionChangedEventManager()
        {
        }
 
        #endregion Constructors
 
        #region Public Methods 

        // 
        //  Public Methods
        //

        ///  
        /// Add a listener to the given source's event.
        ///  
        public static void AddListener(GridViewColumnCollection source, IWeakEventListener listener) 
        {
            CurrentManager.ProtectedAddListener(source, listener); 
        }

        /// 
        /// Remove a listener to the given source's event. 
        /// 
        public static void RemoveListener(GridViewColumnCollection source, IWeakEventListener listener) 
        { 
            CurrentManager.ProtectedRemoveListener(source, listener);
        } 

        #endregion Public Methods

        #region Protected Methods 

        // 
        //  Protected Methods 
        //
 
        /// 
        /// Listen to the given source for the event.
        /// 
        protected override void StartListening(object source) 
        {
            GridViewColumnCollection typedSource = (GridViewColumnCollection)source; 
            typedSource.InternalCollectionChanged += new NotifyCollectionChangedEventHandler(OnCollectionChanged); 
        }
 
        /// 
        /// Stop listening to the given source for the event.
        /// 
        protected override void StopListening(object source) 
        {
            GridViewColumnCollection typedSource = (GridViewColumnCollection)source; 
            typedSource.InternalCollectionChanged -= new NotifyCollectionChangedEventHandler(OnCollectionChanged); 
        }
 
        #endregion Protected Methods

        #region Private Properties
 
        //
        //  Private Properties 
        // 

        // get the event manager for the current thread 
        private static InternalCollectionChangedEventManager CurrentManager
        {
            get
            { 
                Type managerType = typeof(InternalCollectionChangedEventManager);
                InternalCollectionChangedEventManager manager = (InternalCollectionChangedEventManager)GetCurrentManager(managerType); 
 
                // at first use, create and register a new manager
                if (manager == null) 
                {
                    manager = new InternalCollectionChangedEventManager();
                    SetCurrentManager(managerType, manager);
                } 

                return manager; 
            } 
        }
 
        #endregion Private Properties

        #region Private Methods
 
        //
        //  Private Methods 
        // 

        // event handler for CollectionChanged event 
        private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
        {
            DeliverEvent(sender, args);
        } 

        #endregion Private Methods 
    } 
}

// 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