DefinitionBase.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Framework / System / Windows / Controls / DefinitionBase.cs / 1 / DefinitionBase.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Specs 
//      Grid : http://avalon/layout/Specs/Grid.mht 
//      Size Sharing: http://avalon/layout/Specs/Size%20Information%20Sharing.doc
// 
// Misc
//      Grid Tutorial: http://avalon/layout/Documentation%20and%20Tutorials/Grid%20Tutorial.mht
//
// Description: Implementation of base abstract class for ColumnDefinition 
//              and RowDefinition.
// 
// History: 
//  11/17/2003 : olego - Created
// 
//---------------------------------------------------------------------------

using MS.Internal;
using MS.Internal.KnownBoxes; 
using System;
using System.Collections; 
using System.Collections.Generic; 
using System.ComponentModel;
using System.Diagnostics; 
using System.Security.Permissions;
using System.Windows;
using System.Windows.Threading;
 
namespace System.Windows.Controls
{ 
    ///  
    /// DefinitionBase provides core functionality used internally by Grid
    /// and ColumnDefinitionCollection / RowDefinitionCollection 
    /// 
    [Localizability(LocalizationCategory.Ignore)]
    public abstract class DefinitionBase : FrameworkContentElement
    { 
        //-----------------------------------------------------
        // 
        //  Constructors 
        //
        //----------------------------------------------------- 

        #region Constructors

        internal DefinitionBase(bool isColumnDefinition) 
        {
            _isColumnDefinition = isColumnDefinition; 
            _parentIndex = -1; 
        }
 
        #endregion Constructors

        //------------------------------------------------------
        // 
        //  Public Properties
        // 
        //----------------------------------------------------- 

        #region Public Properties 

        /// 
        /// SharedSizeGroup property.
        ///  
        public string SharedSizeGroup
        { 
            get { return (string) GetValue(SharedSizeGroupProperty); } 
            set { SetValue(SharedSizeGroupProperty, value); }
        } 

        #endregion Public Properties

        //------------------------------------------------------ 
        //
        //  Internal Methods 
        // 
        //------------------------------------------------------
 
        #region Internal Methods

        /// 
        /// Callback to notify about entering model tree. 
        /// 
        internal void OnEnterParentTree() 
        { 
            if (_sharedState == null)
            { 
                //  start with getting SharedSizeGroup value.
                //  this property is NOT inhereted which should result in better overall perf.
                string sharedSizeGroupId = SharedSizeGroup;
                if (sharedSizeGroupId != null) 
                {
                    SharedSizeScope privateSharedSizeScope = PrivateSharedSizeScope; 
                    if (privateSharedSizeScope != null) 
                    {
                        _sharedState = privateSharedSizeScope.EnsureSharedState(sharedSizeGroupId); 
                        _sharedState.AddMember(this);
                    }
                }
            } 
        }
 
        ///  
        /// Callback to notify about exitting model tree.
        ///  
        internal void OnExitParentTree()
        {
            _offset = 0;
            if (_sharedState != null) 
            {
                _sharedState.RemoveMember(this); 
                _sharedState = null; 
            }
        } 

        /// 
        /// Performs action preparing definition to enter layout calculation mode.
        ///  
        internal void OnBeforeLayout(Grid grid)
        { 
            //  reset layout state. 
            _minSize = 0;
            LayoutWasUpdated = true; 

            //  defer verification for shared definitions
            if (_sharedState != null)   {   _sharedState.EnsureDeferredValidation(grid);    }
        } 

        ///  
        /// Updates min size. 
        /// 
        /// New size. 
        internal void UpdateMinSize(double minSize)
        {
            _minSize = Math.Max(_minSize, minSize);
        } 

        ///  
        ///  
        /// 
        ///  
        /// This method needs to be internal to be accessable from derived classes.
        /// 
        internal static void OnUserSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            DefinitionBase definition = (DefinitionBase) d;
 
            if (definition.InParentLogicalTree) 
            {
 
                if (definition._sharedState != null)
                {
                    definition._sharedState.Invalidate();
                } 
                else
                { 
                    Grid parentGrid = (Grid) definition.Parent; 

                    if (((GridLength) e.OldValue).GridUnitType != ((GridLength) e.NewValue).GridUnitType) 
                    {
                        parentGrid.Invalidate();
                    }
                    else 
                    {
                        parentGrid.InvalidateMeasure(); 
                    } 
                }
            } 
        }

        /// 
        ///  
        /// 
        ///  
        /// This method needs to be internal to be accessable from derived classes. 
        /// 
        internal static bool IsUserSizePropertyValueValid(object value) 
        {
            return (((GridLength)value).Value >= 0);
        }
 
        /// 
        ///  
        ///  
        /// 
        /// This method needs to be internal to be accessable from derived classes. 
        /// 
        internal static void OnUserMinSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DefinitionBase definition = (DefinitionBase) d; 

            if (definition.InParentLogicalTree) 
            { 
                Grid parentGrid = (Grid) definition.Parent;
                parentGrid.InvalidateMeasure(); 
            }
        }

        ///  
        /// 
        ///  
        ///  
        /// This method needs to be internal to be accessable from derived classes.
        ///  
        internal static bool IsUserMinSizePropertyValueValid(object value)
        {
            double v = (double)value;
            return (!DoubleUtil.IsNaN(v) && v >= 0.0d && !Double.IsPositiveInfinity(v)); 
        }
 
        ///  
        /// 
        ///  
        /// 
        /// This method needs to be internal to be accessable from derived classes.
        /// 
        internal static void OnUserMaxSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            DefinitionBase definition = (DefinitionBase) d; 
 
            if (definition.InParentLogicalTree)
            { 
                Grid parentGrid = (Grid) definition.Parent;
                parentGrid.InvalidateMeasure();
            }
        } 

        ///  
        ///  
        /// 
        ///  
        /// This method needs to be internal to be accessable from derived classes.
        /// 
        internal static bool IsUserMaxSizePropertyValueValid(object value)
        { 
            double v = (double)value;
            return (!DoubleUtil.IsNaN(v) && v >= 0.0d); 
        } 

        ///  
        /// 
        /// 
        /// 
        /// This method reflects Grid.SharedScopeProperty state by setting / clearing 
        /// dynamic property PrivateSharedSizeScopeProperty. Value of PrivateSharedSizeScopeProperty
        /// is a collection of SharedSizeState objects for the scope. 
        /// Also PrivateSharedSizeScopeProperty is FrameworkPropertyMetadataOptions.Inherits property. So that all children 
        /// elements belonging to a certain scope can easily access SharedSizeState collection. As well
        /// as been norified about enter / exit a scope. 
        /// 
        internal static void OnIsSharedSizeScopePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            // 

 
            if ((bool) e.NewValue) 
            {
                SharedSizeScope sharedStatesCollection = new SharedSizeScope(); 
                d.SetValue(PrivateSharedSizeScopeProperty, sharedStatesCollection);
            }
            else
            { 
                d.ClearValue(PrivateSharedSizeScopeProperty);
            } 
        } 

        #endregion Internal Methods 

        //-----------------------------------------------------
        //
        //  Internal Properties 
        //
        //------------------------------------------------------ 
 
        #region Internal Properties
 
        /// 
        /// Returns true if this definition is a part of shared group.
        /// 
        internal bool IsShared 
        {
            get { return (_sharedState != null); } 
        } 

        ///  
        /// Internal accessor to user size field.
        /// 
        internal GridLength UserSize
        { 
            get { return (_sharedState != null ? _sharedState.UserSize : UserSizeValueCache); }
        } 
 
        /// 
        /// Internal accessor to user min size field. 
        /// 
        internal double UserMinSize
        {
            get { return (UserMinSizeValueCache); } 
        }
 
        ///  
        /// Internal accessor to user max size field.
        ///  
        internal double UserMaxSize
        {
            get { return (UserMaxSizeValueCache); }
        } 

        ///  
        /// DefinitionBase's index in the parents collection. 
        /// 
        internal int Index 
        {
            get
            {
                return (_parentIndex); 
            }
            set 
            { 
                Debug.Assert(value >= -1 && _parentIndex != value);
                _parentIndex = value; 
            }
        }

        ///  
        /// Layout-time user size type.
        ///  
        internal Grid.LayoutTimeSizeType SizeType 
        {
            get { return (_sizeType); } 
            set { _sizeType = value; }
        }

        ///  
        /// Returns or sets measure size for the definition.
        ///  
        internal double MeasureSize 
        {
            get { return (_measureSize); } 
            set { _measureSize = value; }
        }

        ///  
        /// Returns definition's layout time type sensitive preferred size.
        ///  
        ///  
        /// Returned value is guaranteed to be true preferred size.
        ///  
        internal double PreferredSize
        {
            get
            { 
                double preferredSize = MinSize;
                if (    _sizeType != Grid.LayoutTimeSizeType.Auto 
                    &&  preferredSize < _measureSize    ) 
                {
                    preferredSize = _measureSize; 
                }
                return (preferredSize);
            }
        } 

        ///  
        /// Returns or sets size cache for the definition. 
        /// 
        internal double SizeCache 
        {
            get { return (_sizeCache); }
            set { _sizeCache = value; }
        } 

        ///  
        /// Returns min size. 
        /// 
        internal double MinSize 
        {
            get
            {
                double minSize = _minSize; 
                if (    UseSharedMinimum
                    &&  _sharedState != null 
                    &&  minSize < _sharedState.MinSize  ) 
                {
                    minSize = _sharedState.MinSize; 
                }
                return (minSize);
            }
        } 

        ///  
        /// Returns min size, always taking into account shared state. 
        /// 
        internal double MinSizeForArrange 
        {
            get
            {
                double minSize = _minSize; 
                if (    _sharedState != null
                    &&  (UseSharedMinimum || !LayoutWasUpdated) 
                    &&  minSize < _sharedState.MinSize  ) 
                {
                    minSize = _sharedState.MinSize; 
                }
                return (minSize);
            }
        } 

        ///  
        /// Offset. 
        /// 
        internal double FinalOffset 
        {
            get { return _offset; }
            set { _offset = value; }
        } 

        ///  
        /// Internal helper to access up-to-date UserSize property value. 
        /// 
        internal GridLength UserSizeValueCache 
        {
            get
            {
                return (GridLength) GetValue( 
                        _isColumnDefinition ?
                        ColumnDefinition.WidthProperty : 
                        RowDefinition.HeightProperty); 
            }
        } 

        /// 
        /// Internal helper to access up-to-date UserMinSize property value.
        ///  
        internal double UserMinSizeValueCache
        { 
            get 
            {
                return (double) GetValue( 
                        _isColumnDefinition ?
                        ColumnDefinition.MinWidthProperty :
                        RowDefinition.MinHeightProperty);
            } 
        }
 
        ///  
        /// Internal helper to access up-to-date UserMaxSize property value.
        ///  
        internal double UserMaxSizeValueCache
        {
            get
            { 
                return (double) GetValue(
                        _isColumnDefinition ? 
                        ColumnDefinition.MaxWidthProperty : 
                        RowDefinition.MaxHeightProperty);
            } 
        }

        /// 
        /// Protected. Returns true if this DefinitionBase instance is in parent's logical tree. 
        /// 
        internal bool InParentLogicalTree 
        { 
            get { return (_parentIndex != -1); }
        } 

        #endregion Internal Properties

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

        /// 
        /// SetFlags is used to set or unset one or multiple 
        /// flags on the object.
        ///  
        private void SetFlags(bool value, Flags flags) 
        {
            _flags = value ? (_flags | flags) : (_flags & (~flags)); 
        }

        /// 
        /// CheckFlagsAnd returns true if all the flags in the 
        /// given bitmask are set on the object.
        ///  
        private bool CheckFlagsAnd(Flags flags) 
        {
            return ((_flags & flags) == flags); 
        }

        /// 
        ///  
        /// 
        private static void OnSharedSizeGroupPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        { 
            DefinitionBase definition = (DefinitionBase) d;
 
            if (definition.InParentLogicalTree)
            {
                string sharedSizeGroupId = (string) e.NewValue;
 
                if (definition._sharedState != null)
                { 
                    //  if definition is already registered AND shared size group id is changing, 
                    //  then un-register the definition from the current shared size state object.
                    definition._sharedState.RemoveMember(definition); 
                    definition._sharedState = null;
                }

                if ((definition._sharedState == null) && (sharedSizeGroupId != null)) 
                {
                    SharedSizeScope privateSharedSizeScope = definition.PrivateSharedSizeScope; 
                    if (privateSharedSizeScope != null) 
                    {
                        //  if definition is not registered and both: shared size group id AND private shared scope 
                        //  are available, then register definition.
                        definition._sharedState = privateSharedSizeScope.EnsureSharedState(sharedSizeGroupId);
                        definition._sharedState.AddMember(definition);
                    } 
                }
            } 
        } 

        ///  
        /// 
        /// 
        /// 
        /// Verifies that Shared Size Group Property string 
        /// a) not empty.
        /// b) contains only letters, digits and underscore ('_'). 
        /// c) does not start with a digit. 
        /// 
        private static bool SharedSizeGroupPropertyValueValid(object value) 
        {
            //  null is default value
            if (value == null)
            { 
                return (true);
            } 
 
            string id = (string)value;
 
            if (id != string.Empty)
            {
                int i = -1;
                while (++i < id.Length) 
                {
                    bool isDigit = Char.IsDigit(id[i]); 
 
                    if (    (i == 0 && isDigit)
                        ||  !(  isDigit 
                            ||  Char.IsLetter(id[i])
                            ||  '_' == id[i]    )   )
                    {
                        break; 
                    }
                } 
 
                if (i == id.Length)
                { 
                    return (true);
                }
            }
 
            return (false);
        } 
 
        /// 
        ///  
        /// 
        /// 
        /// OnPrivateSharedSizeScopePropertyChanged is called when new scope enters or
        /// existing scope just left. In both cases if the DefinitionBase object is already registered 
        /// in SharedSizeState, it should un-register and register itself in a new one.
        ///  
        private static void OnPrivateSharedSizeScopePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            DefinitionBase definition = (DefinitionBase)d; 

            if (definition.InParentLogicalTree)
            {
                SharedSizeScope privateSharedSizeScope = (SharedSizeScope) e.NewValue; 

                if (definition._sharedState != null) 
                { 
                    //  if definition is already registered And shared size scope is changing,
                    //  then un-register the definition from the current shared size state object. 
                    definition._sharedState.RemoveMember(definition);
                    definition._sharedState = null;
                }
 
                if ((definition._sharedState == null) && (privateSharedSizeScope != null))
                { 
                    string sharedSizeGroup = definition.SharedSizeGroup; 
                    if (sharedSizeGroup != null)
                    { 
                        //  if definition is not registered and both: shared size group id AND private shared scope
                        //  are available, then register definition.
                        definition._sharedState = privateSharedSizeScope.EnsureSharedState(definition.SharedSizeGroup);
                        definition._sharedState.AddMember(definition); 
                    }
                } 
            } 
        }
 
        #endregion Private Methods

        //-----------------------------------------------------
        // 
        //  Private Properties
        // 
        //------------------------------------------------------ 

        #region Private Properties 

        /// 
        /// Private getter of shared state collection dynamic property.
        ///  
        private SharedSizeScope PrivateSharedSizeScope
        { 
            get { return (SharedSizeScope) GetValue(PrivateSharedSizeScopeProperty); } 
        }
 
        /// 
        /// Convenience accessor to UseSharedMinimum flag
        /// 
        private bool UseSharedMinimum 
        {
            get { return (CheckFlagsAnd(Flags.UseSharedMinimum)); } 
            set { SetFlags(value, Flags.UseSharedMinimum); } 
        }
 
        /// 
        /// Convenience accessor to LayoutWasUpdated flag
        /// 
        private bool LayoutWasUpdated 
        {
            get { return (CheckFlagsAnd(Flags.LayoutWasUpdated)); } 
            set { SetFlags(value, Flags.LayoutWasUpdated); } 
        }
 
        #endregion Private Properties

        //-----------------------------------------------------
        // 
        //  Private Fields
        // 
        //------------------------------------------------------ 

        #region Private Fields 
        private readonly bool _isColumnDefinition;      //  when "true", this is a ColumnDefinition; when "false" this is a RowDefinition (faster than a type check)
        private Flags _flags;                           //  flags reflecting various aspects of internal state
        private int _parentIndex;                       //  this instance's index in parent's children collection
 
        private Grid.LayoutTimeSizeType _sizeType;      //  layout-time user size type. it may differ from _userSizeValueCache.UnitType when calculating "to-content"
 
        private double _minSize;                        //  used during measure to accumulate size for "Auto" and "Star" DefinitionBase's 
        private double _measureSize;                    //  size, calculated to be the input contstraint size for Child.Measure
        private double _sizeCache;                      //  cache used for various purposes (sorting, caching, etc) during calculations 
        private double _offset;                         //  offset of the DefinitionBase from left / top corner (assuming LTR case)

        private SharedSizeState _sharedState;           //  reference to shared state object this instance is registered with
 
        internal const bool ThisIsColumnDefinition = true;
        internal const bool ThisIsRowDefinition = false; 
 
        #endregion Private Fields
 
        //------------------------------------------------------
        //
        //  Private Structures / Classes
        // 
        //-----------------------------------------------------
 
        #region Private Structures Classes 

        [System.Flags] 
        private enum Flags : byte
        {
            //
            //  bool flags 
            //
            UseSharedMinimum                    =   0x00000020,     //  when "1", definition will take into account shared state's minimum 
            LayoutWasUpdated                    =   0x00000040,     //  set to "1" every time the parent grid is measured 
        }
 
        /// 
        /// Collection of shared states objects for a single scope
        /// 
        private class SharedSizeScope 
        {
            ///  
            /// Returns SharedSizeState object for a given group. 
            /// Creates a new StatedState object if necessary.
            ///  
            internal SharedSizeState EnsureSharedState(string sharedSizeGroup)
            {
                //  check that sharedSizeGroup is not default
                Debug.Assert(sharedSizeGroup != null); 

                SharedSizeState sharedState = _registry[sharedSizeGroup] as SharedSizeState; 
                if (sharedState == null) 
                {
                    sharedState = new SharedSizeState(this, sharedSizeGroup); 
                    _registry[sharedSizeGroup] = sharedState;
                }
                return (sharedState);
            } 

            ///  
            /// Removes an entry in the registry by the given key. 
            /// 
            internal void Remove(object key) 
            {
                Debug.Assert(_registry.Contains(key));
                _registry.Remove(key);
            } 

            private Hashtable _registry = new Hashtable();  //  storage for shared state objects 
        } 

        ///  
        /// Implementation of per shared group state object
        /// 
        private class SharedSizeState
        { 
            /// 
            /// Default ctor. 
            ///  
            internal SharedSizeState(SharedSizeScope sharedSizeScope, string sharedSizeGroupId)
            { 
                Debug.Assert(sharedSizeScope != null && sharedSizeGroupId != null);
                _sharedSizeScope = sharedSizeScope;
                _sharedSizeGroupId = sharedSizeGroupId;
                _registry = new List(); 
                _layoutUpdated = new EventHandler(OnLayoutUpdated);
                _broadcastInvalidation = true; 
            } 

            ///  
            /// Adds / registers a definition instance.
            /// 
            internal void AddMember(DefinitionBase member)
            { 
                Debug.Assert(!_registry.Contains(member));
                _registry.Add(member); 
                Invalidate(); 
            }
 
            /// 
            /// Removes / un-registers a definition instance.
            /// 
            ///  
            /// If the collection of registered definitions becomes empty
            /// instantiates self removal from owner's collection. 
            ///  
            internal void RemoveMember(DefinitionBase member)
            { 
                Invalidate();
                _registry.Remove(member);

                if (_registry.Count == 0) 
                {
                    _sharedSizeScope.Remove(_sharedSizeGroupId); 
                } 
            }
 
            /// 
            /// Propogates invalidations for all registered definitions.
            /// Resets its own state.
            ///  
            internal void Invalidate()
            { 
                _userSizeValid = false; 

                if (_broadcastInvalidation) 
                {
                    for (int i = 0, count = _registry.Count; i < count; ++i)
                    {
                        Grid parentGrid = (Grid)(_registry[i].Parent); 
                        parentGrid.Invalidate();
                    } 
                    _broadcastInvalidation = false; 
                }
            } 

            /// 
            /// Makes sure that one and only one layout updated handler is registered for this shared state.
            ///  
            internal void EnsureDeferredValidation(UIElement layoutUpdatedHost)
            { 
                if (_layoutUpdatedHost == null) 
                {
                    _layoutUpdatedHost = layoutUpdatedHost; 
                    _layoutUpdatedHost.LayoutUpdated += _layoutUpdated;
                }
            }
 
            /// 
            /// DefinitionBase's specific code. 
            ///  
            internal double MinSize
            { 
                get
                {
                    if (!_userSizeValid) { EnsureUserSizeValid(); }
                    return (_minSize); 
                }
            } 
 
            /// 
            /// DefinitionBase's specific code. 
            /// 
            internal GridLength UserSize
            {
                get 
                {
                    if (!_userSizeValid) { EnsureUserSizeValid(); } 
                    return (_userSize); 
                }
            } 

            private void EnsureUserSizeValid()
            {
                _userSize = new GridLength(1, GridUnitType.Auto); 

                for (int i = 0, count = _registry.Count; i < count; ++i) 
                { 
                    Debug.Assert(   _userSize.GridUnitType == GridUnitType.Auto
                                ||  _userSize.GridUnitType == GridUnitType.Pixel    ); 

                    GridLength currentGridLength = _registry[i].UserSizeValueCache;
                    if (currentGridLength.GridUnitType == GridUnitType.Pixel)
                    { 
                        if (_userSize.GridUnitType == GridUnitType.Auto)
                        { 
                            _userSize = currentGridLength; 
                        }
                        else if (_userSize.Value < currentGridLength.Value) 
                        {
                            _userSize = currentGridLength;
                        }
                    } 
                }
                //  taking maximum with user size effectively prevents squishy-ness. 
                //  this is a "solution" to avoid shared definitions from been sized to 
                //  different final size at arrange time, if / when different grids receive
                //  different final sizes. 
                _minSize = _userSize.IsAbsolute ? _userSize.Value : 0.0;

                _userSizeValid = true;
            } 

            ///  
            /// OnLayoutUpdated handler. Validates that all participating definitions 
            /// have updated min size value. Forces another layout update cycle if needed.
            ///  
            private void OnLayoutUpdated(object sender, EventArgs e)
            {
                double sharedMinSize = 0;
 
                //  accumulate min size of all participating definitions
                for (int i = 0, count = _registry.Count; i < count; ++i) 
                { 
                    sharedMinSize = Math.Max(sharedMinSize, _registry[i].MinSize);
                } 

                bool sharedMinSizeChanged = !DoubleUtil.AreClose(_minSize, sharedMinSize);

                //  compare accumulated min size with min sizes of the individual definitions 
                for (int i = 0, count = _registry.Count; i < count; ++i)
                { 
                    DefinitionBase definitionBase = _registry[i]; 

                    if (sharedMinSizeChanged ||  definitionBase.LayoutWasUpdated) 
                    {
                        //  if definition's min size is different, then need to re-measure
                        if (!DoubleUtil.AreClose(sharedMinSize, definitionBase.MinSize))
                        { 
                            Grid parentGrid = (Grid)definitionBase.Parent;
                            parentGrid.InvalidateMeasure(); 
                            definitionBase.UseSharedMinimum = true; 
                        }
                        else 
                        {
                            definitionBase.UseSharedMinimum = false;

                            //  if measure is valid then also need to check arrange. 
                            //  Note: definitionBase.SizeCache is volatile but at this point
                            //  it contains up-to-date final size 
                            if (!DoubleUtil.AreClose(sharedMinSize, definitionBase.SizeCache)) 
                            {
                                Grid parentGrid = (Grid)definitionBase.Parent; 
                                parentGrid.InvalidateArrange();
                            }
                        }
 
                        definitionBase.LayoutWasUpdated = false;
                    } 
                } 

                _minSize = sharedMinSize; 

                _layoutUpdatedHost.LayoutUpdated -= _layoutUpdated;
                _layoutUpdatedHost = null;
 
                _broadcastInvalidation = true;
            } 
 
            private readonly SharedSizeScope _sharedSizeScope;  //  the scope this state belongs to
            private readonly string _sharedSizeGroupId;         //  Id of the shared size group this object is servicing 
            private readonly List _registry;    //  registry of participating definitions
            private readonly EventHandler _layoutUpdated;       //  instance event handler for layout updated event
            private UIElement _layoutUpdatedHost;               //  UIElement for which layout updated event handler is registered
            private bool _broadcastInvalidation;                //  "true" when broadcasting of invalidation is needed 
            private bool _userSizeValid;                        //  "true" when _userSize is up to date
            private GridLength _userSize;                       //  shared state 
            private double _minSize;                            //  shared state 
        }
 
        #endregion Private Structures Classes

        //------------------------------------------------------
        // 
        //  Properties
        // 
        //----------------------------------------------------- 

        #region Properties 

        /// 
        /// Private shared size scope property holds a collection of shared state objects for the a given shared size scope.
        ///  
        /// 
        internal static readonly DependencyProperty PrivateSharedSizeScopeProperty = 
                DependencyProperty.RegisterAttached( 
                        "PrivateSharedSizeScope",
                        typeof(SharedSizeScope), 
                        typeof(DefinitionBase),
                        new FrameworkPropertyMetadata(
                                null,
                                FrameworkPropertyMetadataOptions.Inherits)); 

        ///  
        /// Shared size group property marks column / row definition as belonging to a group "Foo" or "Bar". 
        /// 
        ///  
        /// Value of the Shared Size Group Property must satisfy the following rules:
        /// 
        /// 
        /// String must not be empty. 
        /// 
        ///  
        /// String must consist of letters, digits and underscore ('_') only. 
        /// 
        ///  
        /// String must not start with a digit.
        /// 
        /// 
        ///  
        public static readonly DependencyProperty SharedSizeGroupProperty =
                DependencyProperty.Register( 
                        "SharedSizeGroup", 
                        typeof(string),
                        typeof(DefinitionBase), 
                        new FrameworkPropertyMetadata(new PropertyChangedCallback(OnSharedSizeGroupPropertyChanged)),
                        new ValidateValueCallback(SharedSizeGroupPropertyValueValid));

        ///  
        /// Static ctor. Used for static registration of properties.
        ///  
        static DefinitionBase() 
        {
            PrivateSharedSizeScopeProperty.OverrideMetadata( 
                    typeof(DefinitionBase),
                    new FrameworkPropertyMetadata(new PropertyChangedCallback(OnPrivateSharedSizeScopePropertyChanged)));
        }
 
        #endregion Properties
    } 
} 

// 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.
//  
//
// Specs 
//      Grid : http://avalon/layout/Specs/Grid.mht 
//      Size Sharing: http://avalon/layout/Specs/Size%20Information%20Sharing.doc
// 
// Misc
//      Grid Tutorial: http://avalon/layout/Documentation%20and%20Tutorials/Grid%20Tutorial.mht
//
// Description: Implementation of base abstract class for ColumnDefinition 
//              and RowDefinition.
// 
// History: 
//  11/17/2003 : olego - Created
// 
//---------------------------------------------------------------------------

using MS.Internal;
using MS.Internal.KnownBoxes; 
using System;
using System.Collections; 
using System.Collections.Generic; 
using System.ComponentModel;
using System.Diagnostics; 
using System.Security.Permissions;
using System.Windows;
using System.Windows.Threading;
 
namespace System.Windows.Controls
{ 
    ///  
    /// DefinitionBase provides core functionality used internally by Grid
    /// and ColumnDefinitionCollection / RowDefinitionCollection 
    /// 
    [Localizability(LocalizationCategory.Ignore)]
    public abstract class DefinitionBase : FrameworkContentElement
    { 
        //-----------------------------------------------------
        // 
        //  Constructors 
        //
        //----------------------------------------------------- 

        #region Constructors

        internal DefinitionBase(bool isColumnDefinition) 
        {
            _isColumnDefinition = isColumnDefinition; 
            _parentIndex = -1; 
        }
 
        #endregion Constructors

        //------------------------------------------------------
        // 
        //  Public Properties
        // 
        //----------------------------------------------------- 

        #region Public Properties 

        /// 
        /// SharedSizeGroup property.
        ///  
        public string SharedSizeGroup
        { 
            get { return (string) GetValue(SharedSizeGroupProperty); } 
            set { SetValue(SharedSizeGroupProperty, value); }
        } 

        #endregion Public Properties

        //------------------------------------------------------ 
        //
        //  Internal Methods 
        // 
        //------------------------------------------------------
 
        #region Internal Methods

        /// 
        /// Callback to notify about entering model tree. 
        /// 
        internal void OnEnterParentTree() 
        { 
            if (_sharedState == null)
            { 
                //  start with getting SharedSizeGroup value.
                //  this property is NOT inhereted which should result in better overall perf.
                string sharedSizeGroupId = SharedSizeGroup;
                if (sharedSizeGroupId != null) 
                {
                    SharedSizeScope privateSharedSizeScope = PrivateSharedSizeScope; 
                    if (privateSharedSizeScope != null) 
                    {
                        _sharedState = privateSharedSizeScope.EnsureSharedState(sharedSizeGroupId); 
                        _sharedState.AddMember(this);
                    }
                }
            } 
        }
 
        ///  
        /// Callback to notify about exitting model tree.
        ///  
        internal void OnExitParentTree()
        {
            _offset = 0;
            if (_sharedState != null) 
            {
                _sharedState.RemoveMember(this); 
                _sharedState = null; 
            }
        } 

        /// 
        /// Performs action preparing definition to enter layout calculation mode.
        ///  
        internal void OnBeforeLayout(Grid grid)
        { 
            //  reset layout state. 
            _minSize = 0;
            LayoutWasUpdated = true; 

            //  defer verification for shared definitions
            if (_sharedState != null)   {   _sharedState.EnsureDeferredValidation(grid);    }
        } 

        ///  
        /// Updates min size. 
        /// 
        /// New size. 
        internal void UpdateMinSize(double minSize)
        {
            _minSize = Math.Max(_minSize, minSize);
        } 

        ///  
        ///  
        /// 
        ///  
        /// This method needs to be internal to be accessable from derived classes.
        /// 
        internal static void OnUserSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            DefinitionBase definition = (DefinitionBase) d;
 
            if (definition.InParentLogicalTree) 
            {
 
                if (definition._sharedState != null)
                {
                    definition._sharedState.Invalidate();
                } 
                else
                { 
                    Grid parentGrid = (Grid) definition.Parent; 

                    if (((GridLength) e.OldValue).GridUnitType != ((GridLength) e.NewValue).GridUnitType) 
                    {
                        parentGrid.Invalidate();
                    }
                    else 
                    {
                        parentGrid.InvalidateMeasure(); 
                    } 
                }
            } 
        }

        /// 
        ///  
        /// 
        ///  
        /// This method needs to be internal to be accessable from derived classes. 
        /// 
        internal static bool IsUserSizePropertyValueValid(object value) 
        {
            return (((GridLength)value).Value >= 0);
        }
 
        /// 
        ///  
        ///  
        /// 
        /// This method needs to be internal to be accessable from derived classes. 
        /// 
        internal static void OnUserMinSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DefinitionBase definition = (DefinitionBase) d; 

            if (definition.InParentLogicalTree) 
            { 
                Grid parentGrid = (Grid) definition.Parent;
                parentGrid.InvalidateMeasure(); 
            }
        }

        ///  
        /// 
        ///  
        ///  
        /// This method needs to be internal to be accessable from derived classes.
        ///  
        internal static bool IsUserMinSizePropertyValueValid(object value)
        {
            double v = (double)value;
            return (!DoubleUtil.IsNaN(v) && v >= 0.0d && !Double.IsPositiveInfinity(v)); 
        }
 
        ///  
        /// 
        ///  
        /// 
        /// This method needs to be internal to be accessable from derived classes.
        /// 
        internal static void OnUserMaxSizePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            DefinitionBase definition = (DefinitionBase) d; 
 
            if (definition.InParentLogicalTree)
            { 
                Grid parentGrid = (Grid) definition.Parent;
                parentGrid.InvalidateMeasure();
            }
        } 

        ///  
        ///  
        /// 
        ///  
        /// This method needs to be internal to be accessable from derived classes.
        /// 
        internal static bool IsUserMaxSizePropertyValueValid(object value)
        { 
            double v = (double)value;
            return (!DoubleUtil.IsNaN(v) && v >= 0.0d); 
        } 

        ///  
        /// 
        /// 
        /// 
        /// This method reflects Grid.SharedScopeProperty state by setting / clearing 
        /// dynamic property PrivateSharedSizeScopeProperty. Value of PrivateSharedSizeScopeProperty
        /// is a collection of SharedSizeState objects for the scope. 
        /// Also PrivateSharedSizeScopeProperty is FrameworkPropertyMetadataOptions.Inherits property. So that all children 
        /// elements belonging to a certain scope can easily access SharedSizeState collection. As well
        /// as been norified about enter / exit a scope. 
        /// 
        internal static void OnIsSharedSizeScopePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            // 

 
            if ((bool) e.NewValue) 
            {
                SharedSizeScope sharedStatesCollection = new SharedSizeScope(); 
                d.SetValue(PrivateSharedSizeScopeProperty, sharedStatesCollection);
            }
            else
            { 
                d.ClearValue(PrivateSharedSizeScopeProperty);
            } 
        } 

        #endregion Internal Methods 

        //-----------------------------------------------------
        //
        //  Internal Properties 
        //
        //------------------------------------------------------ 
 
        #region Internal Properties
 
        /// 
        /// Returns true if this definition is a part of shared group.
        /// 
        internal bool IsShared 
        {
            get { return (_sharedState != null); } 
        } 

        ///  
        /// Internal accessor to user size field.
        /// 
        internal GridLength UserSize
        { 
            get { return (_sharedState != null ? _sharedState.UserSize : UserSizeValueCache); }
        } 
 
        /// 
        /// Internal accessor to user min size field. 
        /// 
        internal double UserMinSize
        {
            get { return (UserMinSizeValueCache); } 
        }
 
        ///  
        /// Internal accessor to user max size field.
        ///  
        internal double UserMaxSize
        {
            get { return (UserMaxSizeValueCache); }
        } 

        ///  
        /// DefinitionBase's index in the parents collection. 
        /// 
        internal int Index 
        {
            get
            {
                return (_parentIndex); 
            }
            set 
            { 
                Debug.Assert(value >= -1 && _parentIndex != value);
                _parentIndex = value; 
            }
        }

        ///  
        /// Layout-time user size type.
        ///  
        internal Grid.LayoutTimeSizeType SizeType 
        {
            get { return (_sizeType); } 
            set { _sizeType = value; }
        }

        ///  
        /// Returns or sets measure size for the definition.
        ///  
        internal double MeasureSize 
        {
            get { return (_measureSize); } 
            set { _measureSize = value; }
        }

        ///  
        /// Returns definition's layout time type sensitive preferred size.
        ///  
        ///  
        /// Returned value is guaranteed to be true preferred size.
        ///  
        internal double PreferredSize
        {
            get
            { 
                double preferredSize = MinSize;
                if (    _sizeType != Grid.LayoutTimeSizeType.Auto 
                    &&  preferredSize < _measureSize    ) 
                {
                    preferredSize = _measureSize; 
                }
                return (preferredSize);
            }
        } 

        ///  
        /// Returns or sets size cache for the definition. 
        /// 
        internal double SizeCache 
        {
            get { return (_sizeCache); }
            set { _sizeCache = value; }
        } 

        ///  
        /// Returns min size. 
        /// 
        internal double MinSize 
        {
            get
            {
                double minSize = _minSize; 
                if (    UseSharedMinimum
                    &&  _sharedState != null 
                    &&  minSize < _sharedState.MinSize  ) 
                {
                    minSize = _sharedState.MinSize; 
                }
                return (minSize);
            }
        } 

        ///  
        /// Returns min size, always taking into account shared state. 
        /// 
        internal double MinSizeForArrange 
        {
            get
            {
                double minSize = _minSize; 
                if (    _sharedState != null
                    &&  (UseSharedMinimum || !LayoutWasUpdated) 
                    &&  minSize < _sharedState.MinSize  ) 
                {
                    minSize = _sharedState.MinSize; 
                }
                return (minSize);
            }
        } 

        ///  
        /// Offset. 
        /// 
        internal double FinalOffset 
        {
            get { return _offset; }
            set { _offset = value; }
        } 

        ///  
        /// Internal helper to access up-to-date UserSize property value. 
        /// 
        internal GridLength UserSizeValueCache 
        {
            get
            {
                return (GridLength) GetValue( 
                        _isColumnDefinition ?
                        ColumnDefinition.WidthProperty : 
                        RowDefinition.HeightProperty); 
            }
        } 

        /// 
        /// Internal helper to access up-to-date UserMinSize property value.
        ///  
        internal double UserMinSizeValueCache
        { 
            get 
            {
                return (double) GetValue( 
                        _isColumnDefinition ?
                        ColumnDefinition.MinWidthProperty :
                        RowDefinition.MinHeightProperty);
            } 
        }
 
        ///  
        /// Internal helper to access up-to-date UserMaxSize property value.
        ///  
        internal double UserMaxSizeValueCache
        {
            get
            { 
                return (double) GetValue(
                        _isColumnDefinition ? 
                        ColumnDefinition.MaxWidthProperty : 
                        RowDefinition.MaxHeightProperty);
            } 
        }

        /// 
        /// Protected. Returns true if this DefinitionBase instance is in parent's logical tree. 
        /// 
        internal bool InParentLogicalTree 
        { 
            get { return (_parentIndex != -1); }
        } 

        #endregion Internal Properties

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

        /// 
        /// SetFlags is used to set or unset one or multiple 
        /// flags on the object.
        ///  
        private void SetFlags(bool value, Flags flags) 
        {
            _flags = value ? (_flags | flags) : (_flags & (~flags)); 
        }

        /// 
        /// CheckFlagsAnd returns true if all the flags in the 
        /// given bitmask are set on the object.
        ///  
        private bool CheckFlagsAnd(Flags flags) 
        {
            return ((_flags & flags) == flags); 
        }

        /// 
        ///  
        /// 
        private static void OnSharedSizeGroupPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        { 
            DefinitionBase definition = (DefinitionBase) d;
 
            if (definition.InParentLogicalTree)
            {
                string sharedSizeGroupId = (string) e.NewValue;
 
                if (definition._sharedState != null)
                { 
                    //  if definition is already registered AND shared size group id is changing, 
                    //  then un-register the definition from the current shared size state object.
                    definition._sharedState.RemoveMember(definition); 
                    definition._sharedState = null;
                }

                if ((definition._sharedState == null) && (sharedSizeGroupId != null)) 
                {
                    SharedSizeScope privateSharedSizeScope = definition.PrivateSharedSizeScope; 
                    if (privateSharedSizeScope != null) 
                    {
                        //  if definition is not registered and both: shared size group id AND private shared scope 
                        //  are available, then register definition.
                        definition._sharedState = privateSharedSizeScope.EnsureSharedState(sharedSizeGroupId);
                        definition._sharedState.AddMember(definition);
                    } 
                }
            } 
        } 

        ///  
        /// 
        /// 
        /// 
        /// Verifies that Shared Size Group Property string 
        /// a) not empty.
        /// b) contains only letters, digits and underscore ('_'). 
        /// c) does not start with a digit. 
        /// 
        private static bool SharedSizeGroupPropertyValueValid(object value) 
        {
            //  null is default value
            if (value == null)
            { 
                return (true);
            } 
 
            string id = (string)value;
 
            if (id != string.Empty)
            {
                int i = -1;
                while (++i < id.Length) 
                {
                    bool isDigit = Char.IsDigit(id[i]); 
 
                    if (    (i == 0 && isDigit)
                        ||  !(  isDigit 
                            ||  Char.IsLetter(id[i])
                            ||  '_' == id[i]    )   )
                    {
                        break; 
                    }
                } 
 
                if (i == id.Length)
                { 
                    return (true);
                }
            }
 
            return (false);
        } 
 
        /// 
        ///  
        /// 
        /// 
        /// OnPrivateSharedSizeScopePropertyChanged is called when new scope enters or
        /// existing scope just left. In both cases if the DefinitionBase object is already registered 
        /// in SharedSizeState, it should un-register and register itself in a new one.
        ///  
        private static void OnPrivateSharedSizeScopePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            DefinitionBase definition = (DefinitionBase)d; 

            if (definition.InParentLogicalTree)
            {
                SharedSizeScope privateSharedSizeScope = (SharedSizeScope) e.NewValue; 

                if (definition._sharedState != null) 
                { 
                    //  if definition is already registered And shared size scope is changing,
                    //  then un-register the definition from the current shared size state object. 
                    definition._sharedState.RemoveMember(definition);
                    definition._sharedState = null;
                }
 
                if ((definition._sharedState == null) && (privateSharedSizeScope != null))
                { 
                    string sharedSizeGroup = definition.SharedSizeGroup; 
                    if (sharedSizeGroup != null)
                    { 
                        //  if definition is not registered and both: shared size group id AND private shared scope
                        //  are available, then register definition.
                        definition._sharedState = privateSharedSizeScope.EnsureSharedState(definition.SharedSizeGroup);
                        definition._sharedState.AddMember(definition); 
                    }
                } 
            } 
        }
 
        #endregion Private Methods

        //-----------------------------------------------------
        // 
        //  Private Properties
        // 
        //------------------------------------------------------ 

        #region Private Properties 

        /// 
        /// Private getter of shared state collection dynamic property.
        ///  
        private SharedSizeScope PrivateSharedSizeScope
        { 
            get { return (SharedSizeScope) GetValue(PrivateSharedSizeScopeProperty); } 
        }
 
        /// 
        /// Convenience accessor to UseSharedMinimum flag
        /// 
        private bool UseSharedMinimum 
        {
            get { return (CheckFlagsAnd(Flags.UseSharedMinimum)); } 
            set { SetFlags(value, Flags.UseSharedMinimum); } 
        }
 
        /// 
        /// Convenience accessor to LayoutWasUpdated flag
        /// 
        private bool LayoutWasUpdated 
        {
            get { return (CheckFlagsAnd(Flags.LayoutWasUpdated)); } 
            set { SetFlags(value, Flags.LayoutWasUpdated); } 
        }
 
        #endregion Private Properties

        //-----------------------------------------------------
        // 
        //  Private Fields
        // 
        //------------------------------------------------------ 

        #region Private Fields 
        private readonly bool _isColumnDefinition;      //  when "true", this is a ColumnDefinition; when "false" this is a RowDefinition (faster than a type check)
        private Flags _flags;                           //  flags reflecting various aspects of internal state
        private int _parentIndex;                       //  this instance's index in parent's children collection
 
        private Grid.LayoutTimeSizeType _sizeType;      //  layout-time user size type. it may differ from _userSizeValueCache.UnitType when calculating "to-content"
 
        private double _minSize;                        //  used during measure to accumulate size for "Auto" and "Star" DefinitionBase's 
        private double _measureSize;                    //  size, calculated to be the input contstraint size for Child.Measure
        private double _sizeCache;                      //  cache used for various purposes (sorting, caching, etc) during calculations 
        private double _offset;                         //  offset of the DefinitionBase from left / top corner (assuming LTR case)

        private SharedSizeState _sharedState;           //  reference to shared state object this instance is registered with
 
        internal const bool ThisIsColumnDefinition = true;
        internal const bool ThisIsRowDefinition = false; 
 
        #endregion Private Fields
 
        //------------------------------------------------------
        //
        //  Private Structures / Classes
        // 
        //-----------------------------------------------------
 
        #region Private Structures Classes 

        [System.Flags] 
        private enum Flags : byte
        {
            //
            //  bool flags 
            //
            UseSharedMinimum                    =   0x00000020,     //  when "1", definition will take into account shared state's minimum 
            LayoutWasUpdated                    =   0x00000040,     //  set to "1" every time the parent grid is measured 
        }
 
        /// 
        /// Collection of shared states objects for a single scope
        /// 
        private class SharedSizeScope 
        {
            ///  
            /// Returns SharedSizeState object for a given group. 
            /// Creates a new StatedState object if necessary.
            ///  
            internal SharedSizeState EnsureSharedState(string sharedSizeGroup)
            {
                //  check that sharedSizeGroup is not default
                Debug.Assert(sharedSizeGroup != null); 

                SharedSizeState sharedState = _registry[sharedSizeGroup] as SharedSizeState; 
                if (sharedState == null) 
                {
                    sharedState = new SharedSizeState(this, sharedSizeGroup); 
                    _registry[sharedSizeGroup] = sharedState;
                }
                return (sharedState);
            } 

            ///  
            /// Removes an entry in the registry by the given key. 
            /// 
            internal void Remove(object key) 
            {
                Debug.Assert(_registry.Contains(key));
                _registry.Remove(key);
            } 

            private Hashtable _registry = new Hashtable();  //  storage for shared state objects 
        } 

        ///  
        /// Implementation of per shared group state object
        /// 
        private class SharedSizeState
        { 
            /// 
            /// Default ctor. 
            ///  
            internal SharedSizeState(SharedSizeScope sharedSizeScope, string sharedSizeGroupId)
            { 
                Debug.Assert(sharedSizeScope != null && sharedSizeGroupId != null);
                _sharedSizeScope = sharedSizeScope;
                _sharedSizeGroupId = sharedSizeGroupId;
                _registry = new List(); 
                _layoutUpdated = new EventHandler(OnLayoutUpdated);
                _broadcastInvalidation = true; 
            } 

            ///  
            /// Adds / registers a definition instance.
            /// 
            internal void AddMember(DefinitionBase member)
            { 
                Debug.Assert(!_registry.Contains(member));
                _registry.Add(member); 
                Invalidate(); 
            }
 
            /// 
            /// Removes / un-registers a definition instance.
            /// 
            ///  
            /// If the collection of registered definitions becomes empty
            /// instantiates self removal from owner's collection. 
            ///  
            internal void RemoveMember(DefinitionBase member)
            { 
                Invalidate();
                _registry.Remove(member);

                if (_registry.Count == 0) 
                {
                    _sharedSizeScope.Remove(_sharedSizeGroupId); 
                } 
            }
 
            /// 
            /// Propogates invalidations for all registered definitions.
            /// Resets its own state.
            ///  
            internal void Invalidate()
            { 
                _userSizeValid = false; 

                if (_broadcastInvalidation) 
                {
                    for (int i = 0, count = _registry.Count; i < count; ++i)
                    {
                        Grid parentGrid = (Grid)(_registry[i].Parent); 
                        parentGrid.Invalidate();
                    } 
                    _broadcastInvalidation = false; 
                }
            } 

            /// 
            /// Makes sure that one and only one layout updated handler is registered for this shared state.
            ///  
            internal void EnsureDeferredValidation(UIElement layoutUpdatedHost)
            { 
                if (_layoutUpdatedHost == null) 
                {
                    _layoutUpdatedHost = layoutUpdatedHost; 
                    _layoutUpdatedHost.LayoutUpdated += _layoutUpdated;
                }
            }
 
            /// 
            /// DefinitionBase's specific code. 
            ///  
            internal double MinSize
            { 
                get
                {
                    if (!_userSizeValid) { EnsureUserSizeValid(); }
                    return (_minSize); 
                }
            } 
 
            /// 
            /// DefinitionBase's specific code. 
            /// 
            internal GridLength UserSize
            {
                get 
                {
                    if (!_userSizeValid) { EnsureUserSizeValid(); } 
                    return (_userSize); 
                }
            } 

            private void EnsureUserSizeValid()
            {
                _userSize = new GridLength(1, GridUnitType.Auto); 

                for (int i = 0, count = _registry.Count; i < count; ++i) 
                { 
                    Debug.Assert(   _userSize.GridUnitType == GridUnitType.Auto
                                ||  _userSize.GridUnitType == GridUnitType.Pixel    ); 

                    GridLength currentGridLength = _registry[i].UserSizeValueCache;
                    if (currentGridLength.GridUnitType == GridUnitType.Pixel)
                    { 
                        if (_userSize.GridUnitType == GridUnitType.Auto)
                        { 
                            _userSize = currentGridLength; 
                        }
                        else if (_userSize.Value < currentGridLength.Value) 
                        {
                            _userSize = currentGridLength;
                        }
                    } 
                }
                //  taking maximum with user size effectively prevents squishy-ness. 
                //  this is a "solution" to avoid shared definitions from been sized to 
                //  different final size at arrange time, if / when different grids receive
                //  different final sizes. 
                _minSize = _userSize.IsAbsolute ? _userSize.Value : 0.0;

                _userSizeValid = true;
            } 

            ///  
            /// OnLayoutUpdated handler. Validates that all participating definitions 
            /// have updated min size value. Forces another layout update cycle if needed.
            ///  
            private void OnLayoutUpdated(object sender, EventArgs e)
            {
                double sharedMinSize = 0;
 
                //  accumulate min size of all participating definitions
                for (int i = 0, count = _registry.Count; i < count; ++i) 
                { 
                    sharedMinSize = Math.Max(sharedMinSize, _registry[i].MinSize);
                } 

                bool sharedMinSizeChanged = !DoubleUtil.AreClose(_minSize, sharedMinSize);

                //  compare accumulated min size with min sizes of the individual definitions 
                for (int i = 0, count = _registry.Count; i < count; ++i)
                { 
                    DefinitionBase definitionBase = _registry[i]; 

                    if (sharedMinSizeChanged ||  definitionBase.LayoutWasUpdated) 
                    {
                        //  if definition's min size is different, then need to re-measure
                        if (!DoubleUtil.AreClose(sharedMinSize, definitionBase.MinSize))
                        { 
                            Grid parentGrid = (Grid)definitionBase.Parent;
                            parentGrid.InvalidateMeasure(); 
                            definitionBase.UseSharedMinimum = true; 
                        }
                        else 
                        {
                            definitionBase.UseSharedMinimum = false;

                            //  if measure is valid then also need to check arrange. 
                            //  Note: definitionBase.SizeCache is volatile but at this point
                            //  it contains up-to-date final size 
                            if (!DoubleUtil.AreClose(sharedMinSize, definitionBase.SizeCache)) 
                            {
                                Grid parentGrid = (Grid)definitionBase.Parent; 
                                parentGrid.InvalidateArrange();
                            }
                        }
 
                        definitionBase.LayoutWasUpdated = false;
                    } 
                } 

                _minSize = sharedMinSize; 

                _layoutUpdatedHost.LayoutUpdated -= _layoutUpdated;
                _layoutUpdatedHost = null;
 
                _broadcastInvalidation = true;
            } 
 
            private readonly SharedSizeScope _sharedSizeScope;  //  the scope this state belongs to
            private readonly string _sharedSizeGroupId;         //  Id of the shared size group this object is servicing 
            private readonly List _registry;    //  registry of participating definitions
            private readonly EventHandler _layoutUpdated;       //  instance event handler for layout updated event
            private UIElement _layoutUpdatedHost;               //  UIElement for which layout updated event handler is registered
            private bool _broadcastInvalidation;                //  "true" when broadcasting of invalidation is needed 
            private bool _userSizeValid;                        //  "true" when _userSize is up to date
            private GridLength _userSize;                       //  shared state 
            private double _minSize;                            //  shared state 
        }
 
        #endregion Private Structures Classes

        //------------------------------------------------------
        // 
        //  Properties
        // 
        //----------------------------------------------------- 

        #region Properties 

        /// 
        /// Private shared size scope property holds a collection of shared state objects for the a given shared size scope.
        ///  
        /// 
        internal static readonly DependencyProperty PrivateSharedSizeScopeProperty = 
                DependencyProperty.RegisterAttached( 
                        "PrivateSharedSizeScope",
                        typeof(SharedSizeScope), 
                        typeof(DefinitionBase),
                        new FrameworkPropertyMetadata(
                                null,
                                FrameworkPropertyMetadataOptions.Inherits)); 

        ///  
        /// Shared size group property marks column / row definition as belonging to a group "Foo" or "Bar". 
        /// 
        ///  
        /// Value of the Shared Size Group Property must satisfy the following rules:
        /// 
        /// 
        /// String must not be empty. 
        /// 
        ///  
        /// String must consist of letters, digits and underscore ('_') only. 
        /// 
        ///  
        /// String must not start with a digit.
        /// 
        /// 
        ///  
        public static readonly DependencyProperty SharedSizeGroupProperty =
                DependencyProperty.Register( 
                        "SharedSizeGroup", 
                        typeof(string),
                        typeof(DefinitionBase), 
                        new FrameworkPropertyMetadata(new PropertyChangedCallback(OnSharedSizeGroupPropertyChanged)),
                        new ValidateValueCallback(SharedSizeGroupPropertyValueValid));

        ///  
        /// Static ctor. Used for static registration of properties.
        ///  
        static DefinitionBase() 
        {
            PrivateSharedSizeScopeProperty.OverrideMetadata( 
                    typeof(DefinitionBase),
                    new FrameworkPropertyMetadata(new PropertyChangedCallback(OnPrivateSharedSizeScopePropertyChanged)));
        }
 
        #endregion Properties
    } 
} 

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