Grid.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 / Grid.cs / 1305600 / Grid.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// 
// Description: Grid implementation. 
//
// 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
// 
// History: 
//  09/24/2003 : olego - Created (in griddy prototype branch);
//  10/27/2003 : olego - Ported from griddy prototype branch; 
//  01/20/2004 : olego - Switching to use UIElementCollection;
//
//
 

 
 

 



 

 
 

 



 
using MS.Internal;
using MS.Internal.Controls; 
using MS.Internal.PresentationFramework; 
using MS.Utility;
 
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel; 
using System.Diagnostics;
using System.Windows.Threading; 
using System.Threading; 
using System.Windows;
using System.Windows.Controls; 
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Markup;
 
#pragma warning disable 1634, 1691  // suppressing PreSharp warnings
 
namespace System.Windows.Controls 
{
 
    /// 
    /// Grid
    /// 
    public class Grid : Panel, IAddChild 
    {
 
        //----------------------------------------------------- 
        //
        //  Constructors 
        //
        //-----------------------------------------------------

        #region Constructors 

        ///  
        /// Default constructor. 
        /// 
        public Grid() 
        {
            SetFlags((bool) ShowGridLinesProperty.GetDefaultValue(DependencyObjectType), Flags.ShowGridLinesPropertyValue);
        }
 
        #endregion Constructors
 
        //------------------------------------------------------ 
        //
        //  Public Methods 
        //
        //-----------------------------------------------------

        #region Public Methods 

        ///  
        ///  
        /// 
        void IAddChild.AddChild(object value) 
        {
            if (value == null)
            {
                throw new ArgumentNullException("value"); 
            }
 
            UIElement cell = value as UIElement; 
            if (cell != null)
            { 
                Children.Add(cell);
                return;
            }
 
            throw (new ArgumentException(SR.Get(SRID.Grid_UnexpectedParameterType, value.GetType(), typeof(UIElement)), "value"));
        } 
 
        /// 
        ///  
        /// 
        void IAddChild.AddText(string text)
        {
            XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this); 
        }
 
        ///  
        /// 
        ///  
        protected internal override IEnumerator LogicalChildren
        {
            get
            { 
                // empty panel or a panel being used as the items
                // host has *no* logical children; give empty enumerator 
                bool noChildren = (base.VisualChildrenCount == 0) || IsItemsHost; 

                if (noChildren) 
                {
                    ExtendedData extData = ExtData;

                    if (    extData == null 
                        ||  (   (extData.ColumnDefinitions == null || extData.ColumnDefinitions.Count == 0)
                            &&  (extData.RowDefinitions    == null || extData.RowDefinitions.Count    == 0) ) 
                       ) 
                    {
                        //  grid is empty 
                        return EmptyEnumerator.Instance;
                    }
                }
 
                return (new GridChildrenCollectionEnumeratorSimple(this, !noChildren));
            } 
        } 

        ///  
        /// Helper for setting Column property on a UIElement.
        /// 
        /// UIElement to set Column property on.
        /// Column property value. 
        public static void SetColumn(UIElement element, int value)
        { 
            if (element == null) 
            {
                throw new ArgumentNullException("element"); 
            }

            element.SetValue(ColumnProperty, value);
        } 

        ///  
        /// Helper for reading Column property from a UIElement. 
        /// 
        /// UIElement to read Column property from. 
        /// Column property value.
        [AttachedPropertyBrowsableForChildren()]
        public static int GetColumn(UIElement element)
        { 
            if (element == null)
            { 
                throw new ArgumentNullException("element"); 
            }
 
            return ((int)element.GetValue(ColumnProperty));
        }

        ///  
        /// Helper for setting Row property on a UIElement.
        ///  
        /// UIElement to set Row property on. 
        /// Row property value.
        public static void SetRow(UIElement element, int value) 
        {
            if (element == null)
            {
                throw new ArgumentNullException("element"); 
            }
 
            element.SetValue(RowProperty, value); 
        }
 
        /// 
        /// Helper for reading Row property from a UIElement.
        /// 
        /// UIElement to read Row property from. 
        /// Row property value.
        [AttachedPropertyBrowsableForChildren()] 
        public static int GetRow(UIElement element) 
        {
            if (element == null) 
            {
                throw new ArgumentNullException("element");
            }
 
            return ((int)element.GetValue(RowProperty));
        } 
 
        /// 
        /// Helper for setting ColumnSpan property on a UIElement. 
        /// 
        /// UIElement to set ColumnSpan property on.
        /// ColumnSpan property value.
        public static void SetColumnSpan(UIElement element, int value) 
        {
            if (element == null) 
            { 
                throw new ArgumentNullException("element");
            } 

            element.SetValue(ColumnSpanProperty, value);
        }
 
        /// 
        /// Helper for reading ColumnSpan property from a UIElement. 
        ///  
        /// UIElement to read ColumnSpan property from.
        /// ColumnSpan property value. 
        [AttachedPropertyBrowsableForChildren()]
        public static int GetColumnSpan(UIElement element)
        {
            if (element == null) 
            {
                throw new ArgumentNullException("element"); 
            } 

            return ((int)element.GetValue(ColumnSpanProperty)); 
        }

        /// 
        /// Helper for setting RowSpan property on a UIElement. 
        /// 
        /// UIElement to set RowSpan property on. 
        /// RowSpan property value. 
        public static void SetRowSpan(UIElement element, int value)
        { 
            if (element == null)
            {
                throw new ArgumentNullException("element");
            } 

            element.SetValue(RowSpanProperty, value); 
        } 

        ///  
        /// Helper for reading RowSpan property from a UIElement.
        /// 
        /// UIElement to read RowSpan property from.
        /// RowSpan property value. 
        [AttachedPropertyBrowsableForChildren()]
        public static int GetRowSpan(UIElement element) 
        { 
            if (element == null)
            { 
                throw new ArgumentNullException("element");
            }

            return ((int)element.GetValue(RowSpanProperty)); 
        }
 
        ///  
        /// Helper for setting IsSharedSizeScope property on a UIElement.
        ///  
        /// UIElement to set IsSharedSizeScope property on.
        /// IsSharedSizeScope property value.
        public static void SetIsSharedSizeScope(UIElement element, bool value)
        { 
            if (element == null)
            { 
                throw new ArgumentNullException("element"); 
            }
 
            element.SetValue(IsSharedSizeScopeProperty, value);
        }

        ///  
        /// Helper for reading IsSharedSizeScope property from a UIElement.
        ///  
        /// UIElement to read IsSharedSizeScope property from. 
        /// IsSharedSizeScope property value.
        public static bool GetIsSharedSizeScope(UIElement element) 
        {
            if (element == null)
            {
                throw new ArgumentNullException("element"); 
            }
 
            return ((bool)element.GetValue(IsSharedSizeScopeProperty)); 
        }
 
        #endregion Public Methods

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

        #region Public Properties 

        /// 
        /// ShowGridLines property.
        ///  
        public bool ShowGridLines
        { 
            get { return (CheckFlagsAnd(Flags.ShowGridLinesPropertyValue)); } 
            set { SetValue(ShowGridLinesProperty, value); }
        } 

        /// 
        /// Returns a ColumnDefinitionCollection of column definitions.
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public ColumnDefinitionCollection ColumnDefinitions 
        { 
            get
            { 
                if (_data == null) { _data = new ExtendedData(); }
                if (_data.ColumnDefinitions == null) { _data.ColumnDefinitions = new ColumnDefinitionCollection(this); }

                return (_data.ColumnDefinitions); 
            }
        } 
 
        /// 
        /// Returns a RowDefinitionCollection of row definitions. 
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public RowDefinitionCollection RowDefinitions
        { 
            get
            { 
                if (_data == null) { _data = new ExtendedData(); } 
                if (_data.RowDefinitions == null) { _data.RowDefinitions = new RowDefinitionCollection(this); }
 
                return (_data.RowDefinitions);
            }
        }
 
        #endregion Public Properties
 
        //----------------------------------------------------- 
        //
        //  Protected Methods 
        //
        //------------------------------------------------------

        #region Protected Methods 

        ///  
        ///   Derived class must implement to support Visual children. The method must return 
        ///    the child at the specified index. Index must be between 0 and GetVisualChildrenCount-1.
        /// 
        ///    By default a Visual does not have any children.
        ///
        ///  Remark:
        ///       During this virtual call it is not valid to modify the Visual tree. 
        /// 
        protected override Visual GetVisualChild(int index) 
        { 
            // because "base.Count + 1" for GridLinesRenderer
            // argument checking done at the base class 
            if(index == base.VisualChildrenCount)
            {
                if (_gridLinesRenderer == null)
                { 
                    throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange));
                } 
                return _gridLinesRenderer; 
            }
            else return base.GetVisualChild(index); 

        }

        ///  
        ///  Derived classes override this property to enable the Visual code to enumerate
        ///  the Visual children. Derived classes need to return the number of children 
        ///  from this method. 
        ///
        ///    By default a Visual does not have any children. 
        ///
        ///  Remark: During this virtual method the Visual tree must not be modified.
        /// 
        protected override int VisualChildrenCount 
        {
            //since GridLinesRenderer has not been added as a child, so we do not subtract 
            get { return base.VisualChildrenCount + (_gridLinesRenderer != null ? 1 : 0); } 
        }
 

        /// 
        /// Content measurement.
        ///  
        /// Constraint
        /// Desired size 
        protected override Size MeasureOverride(Size constraint) 
        {
            Size gridDesiredSize; 
            ExtendedData extData = ExtData;

            try
            { 
                EnterCounterScope(Counters.MeasureOverride);
 
                ListenToNotifications = true; 
                MeasureOverrideInProgress = true;
 
                if (extData == null)
                {
                    gridDesiredSize = new Size();
                    UIElementCollection children = InternalChildren; 

                    for (int i = 0, count = children.Count; i < count; ++i) 
                    { 
                        UIElement child = children[i];
                        if (child != null) 
                        {
                            Helper.SetMeasureDataOnChild(this, child, constraint);  // pass along MeasureData so it continues down the tree.
                            child.Measure(constraint);
                            gridDesiredSize.Width = Math.Max(gridDesiredSize.Width, child.DesiredSize.Width); 
                            gridDesiredSize.Height = Math.Max(gridDesiredSize.Height, child.DesiredSize.Height);
                        } 
                    } 
                }
                else 
                {
                    {
                        bool sizeToContentU = double.IsPositiveInfinity(constraint.Width);
                        bool sizeToContentV = double.IsPositiveInfinity(constraint.Height); 

                        // Clear index information and rounding errors 
                        if (RowDefinitionCollectionDirty || ColumnDefinitionCollectionDirty) 
                        {
                            if (_definitionIndices != null) 
                            {
                                Array.Clear(_definitionIndices, 0, _definitionIndices.Length);
                                _definitionIndices = null;
                            } 

                            if (UseLayoutRounding) 
                            { 
                                if (_roundingErrors != null)
                                { 
                                    Array.Clear(_roundingErrors, 0, _roundingErrors.Length);
                                    _roundingErrors = null;
                                }
                            } 
                        }
 
                        ValidateDefinitionsUStructure(); 
                        ValidateDefinitionsLayout(DefinitionsU, sizeToContentU);
 
                        ValidateDefinitionsVStructure();
                        ValidateDefinitionsLayout(DefinitionsV, sizeToContentV);

                        CellsStructureDirty |= (SizeToContentU != sizeToContentU) || (SizeToContentV != sizeToContentV); 

                        SizeToContentU = sizeToContentU; 
                        SizeToContentV = sizeToContentV; 
                    }
 
                    ValidateCells();

                    Debug.Assert(DefinitionsU.Length > 0 && DefinitionsV.Length > 0);
 
                    //  Grid classifies cells into four groups depending on
                    //  the column / row type a cell belongs to (number corresponds to 
                    //  group number): 
                    //
                    //                   Px      Auto     Star 
                    //               +--------+--------+--------+
                    //               |        |        |        |
                    //            Px |    1   |    1   |    3   |
                    //               |        |        |        | 
                    //               +--------+--------+--------+
                    //               |        |        |        | 
                    //          Auto |    1   |    1   |    3   | 
                    //               |        |        |        |
                    //               +--------+--------+--------+ 
                    //               |        |        |        |
                    //          Star |    4   |    2   |    4   |
                    //               |        |        |        |
                    //               +--------+--------+--------+ 
                    //
                    //  The group number indicates the order in which cells are measured. 
                    //  Certain order is necessary to be able to dynamically resolve star 
                    //  columns / rows sizes which are used as input for measuring of
                    //  the cells belonging to them. 
                    //
                    //  However, there are cases when topology of a grid causes cyclical
                    //  size dependences. For example:
                    // 
                    //
                    //                         column width="Auto"      column width="*" 
                    //                      +----------------------+----------------------+ 
                    //                      |                      |                      |
                    //                      |                      |                      | 
                    //                      |                      |                      |
                    //                      |                      |                      |
                    //  row height="Auto"   |                      |      cell 1 2        |
                    //                      |                      |                      | 
                    //                      |                      |                      |
                    //                      |                      |                      | 
                    //                      |                      |                      | 
                    //                      +----------------------+----------------------+
                    //                      |                      |                      | 
                    //                      |                      |                      |
                    //                      |                      |                      |
                    //                      |                      |                      |
                    //  row height="*"      |       cell 2 1       |                      | 
                    //                      |                      |                      |
                    //                      |                      |                      | 
                    //                      |                      |                      | 
                    //                      |                      |                      |
                    //                      +----------------------+----------------------+ 
                    //
                    //  In order to accurately calculate constraint width for "cell 1 2"
                    //  (which is the remaining of grid's available width and calculated
                    //  value of Auto column), "cell 2 1" needs to be calculated first, 
                    //  as it contributes to the Auto column's calculated value.
                    //  At the same time in order to accurately calculate constraint 
                    //  height for "cell 2 1", "cell 1 2" needs to be calcualted first, 
                    //  as it contributes to Auto row height, which is used in the
                    //  computation of Star row resolved height. 
                    //
                    //  to "break" this cyclical dependency we are making (arbitrary)
                    //  decision to treat cells like "cell 2 1" as if they appear in Auto
                    //  rows. And then recalculate them one more time when star row 
                    //  heights are resolved.
                    // 
                    //  (Or more strictly) the code below implement the following logic: 
                    //
                    //                       +---------+ 
                    //                       |  enter  |
                    //                       +---------+
                    //                            |
                    //                            V 
                    //                    +----------------+
                    //                    | Measure Group1 | 
                    //                    +----------------+ 
                    //                            |
                    //                            V 
                    //                          / - \
                    //                        /       \
                    //                  Y   /    Can    \    N
                    //            +--------|   Resolve   |-----------+ 
                    //            |         \  StarsV?  /            |
                    //            |           \       /              | 
                    //            |             \ - /                | 
                    //            V                                  V
                    //    +----------------+                       / - \ 
                    //    | Resolve StarsV |                     /       \
                    //    +----------------+               Y   /    Can    \    N
                    //            |                      +----|   Resolve   |------+
                    //            V                      |     \  StarsU?  /       | 
                    //    +----------------+             |       \       /         |
                    //    | Measure Group2 |             |         \ - /           | 
                    //    +----------------+             |                         V 
                    //            |                      |                 +-----------------+
                    //            V                      |                 | Measure Group2' | 
                    //    +----------------+             |                 +-----------------+
                    //    | Resolve StarsU |             |                         |
                    //    +----------------+             V                         V
                    //            |              +----------------+        +----------------+ 
                    //            V              | Resolve StarsU |        | Resolve StarsU |
                    //    +----------------+     +----------------+        +----------------+ 
                    //    | Measure Group3 |             |                         | 
                    //    +----------------+             V                         V
                    //            |              +----------------+        +----------------+ 
                    //            |              | Measure Group3 |        | Measure Group3 |
                    //            |              +----------------+        +----------------+
                    //            |                      |                         |
                    //            |                      V                         V 
                    //            |              +----------------+        +----------------+
                    //            |              | Resolve StarsV |        | Resolve StarsV | 
                    //            |              +----------------+        +----------------+ 
                    //            |                      |                         |
                    //            |                      |                         V 
                    //            |                      |                +------------------+
                    //            |                      |                | Measure Group2'' |
                    //            |                      |                +------------------+
                    //            |                      |                         | 
                    //            +----------------------+-------------------------+
                    //                                   | 
                    //                                   V 
                    //                           +----------------+
                    //                           | Measure Group4 | 
                    //                           +----------------+
                    //                                   |
                    //                                   V
                    //                               +--------+ 
                    //                               |  exit  |
                    //                               +--------+ 
                    // 
                    //  where:
                    //  *   all [Measure GroupN] - regular children measure process - 
                    //      each cell is measured given contraint size as an input
                    //      and each cell's desired size is accumulated on the
                    //      corresponding column / row;
                    //  *   [Measure Group2'] - is when each cell is measured with 
                    //      infinit height as a constraint and a cell's desired
                    //      height is ignored; 
                    //  *   [Measure Groups''] - is when each cell is measured (second 
                    //      time during single Grid.MeasureOverride) regularly but its
                    //      returned width is ignored; 
                    //
                    //  This algorithm is believed to be as close to ideal as possible.
                    //  It has the following drawbacks:
                    //  *   cells belonging to Group2 can be called to measure twice; 
                    //  *   iff during second measure a cell belonging to Group2 returns
                    //      desired width greater than desired width returned the first 
                    //      time, such a cell is going to be clipped, even though it 
                    //      appears in Auto column.
                    // 

                    MeasureCellsGroup(extData.CellGroup1, constraint, false, false);

                    { 
                        //  after Group1 is measured,  only Group3 may have cells belonging to Auto rows.
                        bool canResolveStarsV = !HasGroup3CellsInAutoRows; 
 
                        if (canResolveStarsV)
                        { 
                            if (HasStarCellsV) { ResolveStar(DefinitionsV, constraint.Height); }
                            MeasureCellsGroup(extData.CellGroup2, constraint, false, false);
                            if (HasStarCellsU) { ResolveStar(DefinitionsU, constraint.Width); }
                            MeasureCellsGroup(extData.CellGroup3, constraint, false, false); 
                        }
                        else 
                        { 
                            //  if at least one cell exists in Group2, it must be measured before
                            //  StarsU can be resolved. 
                            bool canResolveStarsU = extData.CellGroup2 > PrivateCells.Length;
                            if (canResolveStarsU)
                            {
                                if (HasStarCellsU) { ResolveStar(DefinitionsU, constraint.Width); } 
                                MeasureCellsGroup(extData.CellGroup3, constraint, false, false);
                                if (HasStarCellsV) { ResolveStar(DefinitionsV, constraint.Height); } 
                            } 
                            else
                            { 
                                MeasureCellsGroup(extData.CellGroup2, constraint, false, true);
                                if (HasStarCellsU) { ResolveStar(DefinitionsU, constraint.Width); }
                                MeasureCellsGroup(extData.CellGroup3, constraint, false, false);
                                if (HasStarCellsV) { ResolveStar(DefinitionsV, constraint.Height); } 
                                MeasureCellsGroup(extData.CellGroup2, constraint, true, false);
                            } 
                        } 
                    }
 
                    MeasureCellsGroup(extData.CellGroup4, constraint, false, false);

                    EnterCounter(Counters._CalculateDesiredSize);
                    gridDesiredSize = new Size( 
                            CalculateDesiredSize(DefinitionsU),
                            CalculateDesiredSize(DefinitionsV)); 
                    ExitCounter(Counters._CalculateDesiredSize); 
                }
            } 
            finally
            {
                MeasureOverrideInProgress = false;
                ExitCounterScope(Counters.MeasureOverride); 
            }
 
            return (gridDesiredSize); 
        }
 
        /// 
        /// Content arrangement.
        /// 
        /// Arrange size 
        protected override Size ArrangeOverride(Size arrangeSize)
        { 
            try 
            {
                EnterCounterScope(Counters.ArrangeOverride); 

                ArrangeOverrideInProgress = true;

                if (_data == null) 
                {
                    UIElementCollection children = InternalChildren; 
 
                    for (int i = 0, count = children.Count; i < count; ++i)
                    { 
                        UIElement child = children[i];
                        if (child != null)
                        {
                            child.Arrange(new Rect(arrangeSize)); 
                        }
                    } 
                } 
                else
                { 
                    Debug.Assert(DefinitionsU.Length > 0 && DefinitionsV.Length > 0);

                    EnterCounter(Counters._SetFinalSize);
 
                    SetFinalSize(DefinitionsU, arrangeSize.Width, true);
                    SetFinalSize(DefinitionsV, arrangeSize.Height, false); 
 
                    ExitCounter(Counters._SetFinalSize);
 
                    UIElementCollection children = InternalChildren;

                    for (int currentCell = 0; currentCell < PrivateCells.Length; ++currentCell)
                    { 
                        UIElement cell = children[currentCell];
                        if (cell == null) 
                        { 
                            continue;
                        } 

                        int columnIndex = PrivateCells[currentCell].ColumnIndex;
                        int rowIndex = PrivateCells[currentCell].RowIndex;
                        int columnSpan = PrivateCells[currentCell].ColumnSpan; 
                        int rowSpan = PrivateCells[currentCell].RowSpan;
 
                        Rect cellRect = new Rect( 
                            columnIndex == 0 ? 0.0 : DefinitionsU[columnIndex].FinalOffset,
                            rowIndex == 0 ? 0.0 : DefinitionsV[rowIndex].FinalOffset, 
                            GetFinalSizeForRange(DefinitionsU, columnIndex, columnSpan),
                            GetFinalSizeForRange(DefinitionsV, rowIndex, rowSpan)   );

                        EnterCounter(Counters._ArrangeChildHelper2); 
                        cell.Arrange(cellRect);
                        ExitCounter(Counters._ArrangeChildHelper2); 
                    } 

                    //  update render bound on grid lines renderer visual 
                    GridLinesRenderer gridLinesRenderer = EnsureGridLinesRenderer();
                    if (gridLinesRenderer != null)
                    {
                        gridLinesRenderer.UpdateRenderBounds(arrangeSize); 
                    }
                } 
            } 
            finally
            { 
                SetValid();
                ArrangeOverrideInProgress = false;
                ExitCounterScope(Counters.ArrangeOverride);
            } 
            return (arrangeSize);
        } 
 
        /// 
        ///  
        /// 
        protected internal override void OnVisualChildrenChanged(
            DependencyObject visualAdded,
            DependencyObject visualRemoved) 
        {
            CellsStructureDirty = true; 
 
            base.OnVisualChildrenChanged(visualAdded, visualRemoved);
        } 

        #endregion Protected Methods

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

        /// 
        ///     Invalidates grid caches and makes the grid dirty for measure. 
        /// 
        internal void Invalidate() 
        { 
            CellsStructureDirty = true;
            InvalidateMeasure(); 
        }

        /// 
        ///     Returns final width for a column. 
        /// 
        ///  
        ///     Used from public ColumnDefinition ActualWidth. Calculates final width using offset data. 
        /// 
        internal double GetFinalColumnDefinitionWidth(int columnIndex) 
        {
            double value = 0.0;

            Invariant.Assert(_data != null); 

            //  actual value calculations require structure to be up-to-date 
            if (!ColumnDefinitionCollectionDirty) 
            {
                DefinitionBase[] definitions = DefinitionsU; 
                value = definitions[(columnIndex + 1) % definitions.Length].FinalOffset;
                if (columnIndex != 0) { value -= definitions[columnIndex].FinalOffset; }
            }
            return (value); 
        }
 
        ///  
        ///     Returns final height for a row.
        ///  
        /// 
        ///     Used from public RowDefinition ActualHeight. Calculates final height using offset data.
        /// 
        internal double GetFinalRowDefinitionHeight(int rowIndex) 
        {
            double value = 0.0; 
 
            Invariant.Assert(_data != null);
 
            //  actual value calculations require structure to be up-to-date
            if (!RowDefinitionCollectionDirty)
            {
                DefinitionBase[] definitions = DefinitionsV; 
                value = definitions[(rowIndex + 1) % definitions.Length].FinalOffset;
                if (rowIndex != 0) { value -= definitions[rowIndex].FinalOffset; } 
            } 
            return (value);
        } 

        #endregion Internal Methods

        //----------------------------------------------------- 
        //
        //  Internal Properties 
        // 
        //------------------------------------------------------
 
        #region Internal Properties

        /// 
        /// Convenience accessor to MeasureOverrideInProgress bit flag. 
        /// 
        internal bool MeasureOverrideInProgress 
        { 
            get { return (CheckFlagsAnd(Flags.MeasureOverrideInProgress)); }
            set { SetFlags(value, Flags.MeasureOverrideInProgress); } 
        }

        /// 
        /// Convenience accessor to ArrangeOverrideInProgress bit flag. 
        /// 
        internal bool ArrangeOverrideInProgress 
        { 
            get { return (CheckFlagsAnd(Flags.ArrangeOverrideInProgress)); }
            set { SetFlags(value, Flags.ArrangeOverrideInProgress); } 
        }

        /// 
        /// Convenience accessor to ValidDefinitionsUStructure bit flag. 
        /// 
        internal bool ColumnDefinitionCollectionDirty 
        { 
            get { return (!CheckFlagsAnd(Flags.ValidDefinitionsUStructure)); }
            set { SetFlags(!value, Flags.ValidDefinitionsUStructure); } 
        }

        /// 
        /// Convenience accessor to ValidDefinitionsVStructure bit flag. 
        /// 
        internal bool RowDefinitionCollectionDirty 
        { 
            get { return (!CheckFlagsAnd(Flags.ValidDefinitionsVStructure)); }
            set { SetFlags(!value, Flags.ValidDefinitionsVStructure); } 
        }

        #endregion Internal Properties
 
        //-----------------------------------------------------
        // 
        //  Private Methods 
        //
        //------------------------------------------------------ 

        #region Private Methods

        ///  
        /// Lays out cells according to rows and columns, and creates lookup grids.
        ///  
        private void ValidateCells() 
        {
            EnterCounter(Counters._ValidateCells); 

            if (CellsStructureDirty)
            {
                ValidateCellsCore(); 
                CellsStructureDirty = false;
            } 
 
            ExitCounter(Counters._ValidateCells);
        } 

        /// 
        /// ValidateCellsCore
        ///  
        private void ValidateCellsCore()
        { 
            UIElementCollection children = InternalChildren; 
            ExtendedData extData = ExtData;
 
            extData.CellCachesCollection = new CellCache[children.Count];
            extData.CellGroup1 = int.MaxValue;
            extData.CellGroup2 = int.MaxValue;
            extData.CellGroup3 = int.MaxValue; 
            extData.CellGroup4 = int.MaxValue;
 
            bool hasStarCellsU = false; 
            bool hasStarCellsV = false;
            bool hasGroup3CellsInAutoRows = false; 

            for (int i = PrivateCells.Length - 1; i >= 0; --i)
            {
                UIElement child = children[i]; 
                if (child == null)
                { 
                    continue; 
                }
 
                CellCache cell = new CellCache();

                //
                //  read and cache child positioning properties 
                //
 
                //  read indices from the corresponding properties 
                //      clamp to value < number_of_columns
                //      column >= 0 is guaranteed by property value validation callback 
                cell.ColumnIndex = Math.Min(GetColumn(child), DefinitionsU.Length - 1);
                //      clamp to value < number_of_rows
                //      row >= 0 is guaranteed by property value validation callback
                cell.RowIndex = Math.Min(GetRow(child), DefinitionsV.Length - 1); 

                //  read span properties 
                //      clamp to not exceed beyond right side of the grid 
                //      column_span > 0 is guaranteed by property value validation callback
                cell.ColumnSpan = Math.Min(GetColumnSpan(child), DefinitionsU.Length - cell.ColumnIndex); 

                //      clamp to not exceed beyond bottom side of the grid
                //      row_span > 0 is guaranteed by property value validation callback
                cell.RowSpan = Math.Min(GetRowSpan(child), DefinitionsV.Length - cell.RowIndex); 

                Debug.Assert(0 <= cell.ColumnIndex && cell.ColumnIndex < DefinitionsU.Length); 
                Debug.Assert(0 <= cell.RowIndex && cell.RowIndex < DefinitionsV.Length); 

                // 
                //  calculate and cache length types for the child
                //

                cell.SizeTypeU = GetLengthTypeForRange(DefinitionsU, cell.ColumnIndex, cell.ColumnSpan); 
                cell.SizeTypeV = GetLengthTypeForRange(DefinitionsV, cell.RowIndex, cell.RowSpan);
 
                hasStarCellsU |= cell.IsStarU; 
                hasStarCellsV |= cell.IsStarV;
 
                //
                //  distribute cells into four groups.
                //
 
                if (!cell.IsStarV)
                { 
                    if (!cell.IsStarU) 
                    {
                        cell.Next = extData.CellGroup1; 
                        extData.CellGroup1 = i;
                    }
                    else
                    { 
                        cell.Next = extData.CellGroup3;
                        extData.CellGroup3 = i; 
 
                        //  remember if this cell belongs to auto row
                        hasGroup3CellsInAutoRows |= cell.IsAutoV; 
                    }
                }
                else
                { 
                    if (    cell.IsAutoU
                            //  note below: if spans through Star column it is NOT Auto 
                        &&  !cell.IsStarU ) 
                    {
                        cell.Next = extData.CellGroup2; 
                        extData.CellGroup2 = i;
                    }
                    else
                    { 
                        cell.Next = extData.CellGroup4;
                        extData.CellGroup4 = i; 
                    } 
                }
 
                PrivateCells[i] = cell;
            }

            HasStarCellsU = hasStarCellsU; 
            HasStarCellsV = hasStarCellsV;
            HasGroup3CellsInAutoRows = hasGroup3CellsInAutoRows; 
        } 

        ///  
        /// Initializes DefinitionsU memeber either to user supplied ColumnDefinitions collection
        /// or to a default single element collection. DefinitionsU gets trimmed to size.
        /// 
        ///  
        /// This is one of two methods, where ColumnDefinitions and DefinitionsU are directly accessed.
        /// All the rest measure / arrange / render code must use DefinitionsU. 
        ///  
        private void ValidateDefinitionsUStructure()
        { 
            EnterCounter(Counters._ValidateColsStructure);

            if (ColumnDefinitionCollectionDirty)
            { 
                ExtendedData extData = ExtData;
 
                if (extData.ColumnDefinitions == null) 
                {
                    if (extData.DefinitionsU == null) 
                    {
                        extData.DefinitionsU = new DefinitionBase[] { new ColumnDefinition() };
                    }
                } 
                else
                { 
                    extData.ColumnDefinitions.InternalTrimToSize(); 

                    if (extData.ColumnDefinitions.InternalCount == 0) 
                    {
                        //  if column definitions collection is empty
                        //  mockup array with one column
                        extData.DefinitionsU = new DefinitionBase[] { new ColumnDefinition() }; 
                    }
                    else 
                    { 
                        extData.DefinitionsU = extData.ColumnDefinitions.InternalItems;
                    } 
                }

                ColumnDefinitionCollectionDirty = false;
            } 

            Debug.Assert(ExtData.DefinitionsU != null && ExtData.DefinitionsU.Length > 0); 
 
            ExitCounter(Counters._ValidateColsStructure);
        } 

        /// 
        /// Initializes DefinitionsV memeber either to user supplied RowDefinitions collection
        /// or to a default single element collection. DefinitionsV gets trimmed to size. 
        /// 
        ///  
        /// This is one of two methods, where RowDefinitions and DefinitionsV are directly accessed. 
        /// All the rest measure / arrange / render code must use DefinitionsV.
        ///  
        private void ValidateDefinitionsVStructure()
        {
            EnterCounter(Counters._ValidateRowsStructure);
 
            if (RowDefinitionCollectionDirty)
            { 
                ExtendedData extData = ExtData; 

                if (extData.RowDefinitions == null) 
                {
                    if (extData.DefinitionsV == null)
                    {
                        extData.DefinitionsV = new DefinitionBase[] { new RowDefinition() }; 
                    }
                } 
                else 
                {
                    extData.RowDefinitions.InternalTrimToSize(); 

                    if (extData.RowDefinitions.InternalCount == 0)
                    {
                        //  if row definitions collection is empty 
                        //  mockup array with one row
                        extData.DefinitionsV = new DefinitionBase[] { new RowDefinition() }; 
                    } 
                    else
                    { 
                        extData.DefinitionsV = extData.RowDefinitions.InternalItems;
                    }
                }
 
                RowDefinitionCollectionDirty = false;
            } 
 
            Debug.Assert(ExtData.DefinitionsV != null && ExtData.DefinitionsV.Length > 0);
 
            ExitCounter(Counters._ValidateRowsStructure);
        }

        ///  
        /// Validates layout time size type information on given array of definitions.
        /// Sets MinSize and MeasureSizes. 
        ///  
        /// Array of definitions to update.
        /// if "true" then star definitions are treated as Auto. 
        private void ValidateDefinitionsLayout(
            DefinitionBase[] definitions,
            bool treatStarAsAuto)
        { 
            for (int i = 0; i < definitions.Length; ++i)
            { 
                definitions[i].OnBeforeLayout(this); 

                double userMinSize = definitions[i].UserMinSize; 
                double userMaxSize = definitions[i].UserMaxSize;
                double userSize = 0;

                switch (definitions[i].UserSize.GridUnitType) 
                {
                    case (GridUnitType.Pixel): 
                        definitions[i].SizeType = LayoutTimeSizeType.Pixel; 
                        userSize = definitions[i].UserSize.Value;
                        // this was brought with NewLayout and defeats squishy behavior 
                        userMinSize = Math.Max(userMinSize, Math.Min(userSize, userMaxSize));
                        break;
                    case (GridUnitType.Auto):
                        definitions[i].SizeType = LayoutTimeSizeType.Auto; 
                        userSize = double.PositiveInfinity;
                        break; 
                    case (GridUnitType.Star): 
                        if (treatStarAsAuto)
                        { 
                            definitions[i].SizeType = LayoutTimeSizeType.Auto;
                            userSize = double.PositiveInfinity;
                        }
                        else 
                        {
                            definitions[i].SizeType = LayoutTimeSizeType.Star; 
                            userSize = double.PositiveInfinity; 
                        }
                        break; 
                    default:
                        Debug.Assert(false);
                        break;
                } 

                definitions[i].UpdateMinSize(userMinSize); 
                definitions[i].MeasureSize = Math.Max(userMinSize, Math.Min(userSize, userMaxSize)); 
            }
        } 

        /// 
        /// Measures one group of cells.
        ///  
        /// Head index of the cells chain.
        /// Reference size for spanned cells 
        /// calculations. 
        /// When "true" cells' desired
        /// width is not registered in columns. 
        /// Passed through to MeasureCell.
        /// When "true" cells' desired height is not registered in rows.
        private void MeasureCellsGroup(
            int cellsHead, 
            Size referenceSize,
            bool ignoreDesiredSizeU, 
            bool forceInfinityV) 
        {
            if (cellsHead >= PrivateCells.Length) 
            {
                return;
            }
 
            UIElementCollection children = InternalChildren;
            Hashtable spanStore = null; 
            bool ignoreDesiredSizeV = forceInfinityV; 

            int i = cellsHead; 
            do
            {
                MeasureCell(i, forceInfinityV);
 
                if (!ignoreDesiredSizeU)
                { 
                    if (PrivateCells[i].ColumnSpan == 1) 
                    {
                        DefinitionsU[PrivateCells[i].ColumnIndex].UpdateMinSize(Math.Min(children[i].DesiredSize.Width, DefinitionsU[PrivateCells[i].ColumnIndex].UserMaxSize)); 
                    }
                    else
                    {
                        RegisterSpan( 
                            ref spanStore,
                            PrivateCells[i].ColumnIndex, 
                            PrivateCells[i].ColumnSpan, 
                            true,
                            children[i].DesiredSize.Width); 
                    }
                }

                if (!ignoreDesiredSizeV) 
                {
                    if (PrivateCells[i].RowSpan == 1) 
                    { 
                        DefinitionsV[PrivateCells[i].RowIndex].UpdateMinSize(Math.Min(children[i].DesiredSize.Height, DefinitionsV[PrivateCells[i].RowIndex].UserMaxSize));
                    } 
                    else
                    {
                        RegisterSpan(
                            ref spanStore, 
                            PrivateCells[i].RowIndex,
                            PrivateCells[i].RowSpan, 
                            false, 
                            children[i].DesiredSize.Height);
                    } 
                }

                i = PrivateCells[i].Next;
            } while (i < PrivateCells.Length); 

            if (spanStore != null) 
            { 
                foreach (DictionaryEntry e in spanStore)
                { 
                    SpanKey key = (SpanKey)e.Key;
                    double requestedSize = (double)e.Value;

                    EnsureMinSizeInDefinitionRange( 
                        key.U ? DefinitionsU : DefinitionsV,
                        key.Start, 
                        key.Count, 
                        requestedSize,
                        key.U ? referenceSize.Width : referenceSize.Height); 
                }
            }
        }
 
        /// 
        /// Helper method to register a span information for delayed processing. 
        ///  
        /// Reference to a hashtable object used as storage.
        /// Span starting index. 
        /// Span count.
        /// true if this is a column span. false if this is a row span.
        /// Value to store. If an entry already exists the biggest value is stored.
        private static void RegisterSpan( 
            ref Hashtable store,
            int start, 
            int count, 
            bool u,
            double value) 
        {
            if (store == null)
            {
                store = new Hashtable(); 
            }
 
            SpanKey key = new SpanKey(start, count, u); 
            object o = store[key];
 
            if (    o == null
                ||  value > (double)o   )
            {
                store[key] = value; 
            }
        } 
 
        /// 
        /// Takes care of measuring a single cell. 
        /// 
        /// Index of the cell to measure.
        /// If "true" then cell is always
        /// calculated to infinite height. 
        private void MeasureCell(
            int cell, 
            bool forceInfinityV) 
        {
            EnterCounter(Counters._MeasureCell); 

            double cellMeasureWidth;
            double cellMeasureHeight;
 
            if (    PrivateCells[cell].IsAutoU
                &&  !PrivateCells[cell].IsStarU   ) 
            { 
                //  if cell belongs to at least one Auto column and not a single Star column
                //  then it should be calculated "to content", thus it is possible to "shortcut" 
                //  calculations and simply assign PositiveInfinity here.
                cellMeasureWidth = double.PositiveInfinity;
            }
            else 
            {
                //  otherwise... 
                cellMeasureWidth = GetMeasureSizeForRange( 
                                        DefinitionsU,
                                        PrivateCells[cell].ColumnIndex, 
                                        PrivateCells[cell].ColumnSpan);
            }

            if (forceInfinityV) 
            {
                cellMeasureHeight = double.PositiveInfinity; 
            } 
            else if (   PrivateCells[cell].IsAutoV
                    &&  !PrivateCells[cell].IsStarV   ) 
            {
                //  if cell belongs to at least one Auto row and not a single Star row
                //  then it should be calculated "to content", thus it is possible to "shortcut"
                //  calculations and simply assign PositiveInfinity here. 
                cellMeasureHeight = double.PositiveInfinity;
            } 
            else 
            {
                cellMeasureHeight = GetMeasureSizeForRange( 
                                        DefinitionsV,
                                        PrivateCells[cell].RowIndex,
                                        PrivateCells[cell].RowSpan);
            } 

            EnterCounter(Counters.__MeasureChild); 
            UIElement child = InternalChildren[cell]; 
            if (child != null)
            { 
                Size childConstraint = new Size(cellMeasureWidth, cellMeasureHeight);
                Helper.SetMeasureDataOnChild(this, child, childConstraint);  // pass along MeasureData so it continues down the tree.
                child.Measure(childConstraint);
            } 
            ExitCounter(Counters.__MeasureChild);
 
            ExitCounter(Counters._MeasureCell); 
        }
 

        /// 
        /// Calculates one dimensional measure size for given definitions' range.
        ///  
        /// Source array of definitions to read values from.
        /// Starting index of the range. 
        /// Number of definitions included in the range. 
        /// Calculated measure size.
        ///  
        /// For "Auto" definitions MinWidth is used in place of PreferredSize.
        /// 
        private double GetMeasureSizeForRange(
            DefinitionBase[] definitions, 
            int start,
            int count) 
        { 
            Debug.Assert(0 < count && 0 <= start && (start + count) <= definitions.Length);
 
            double measureSize = 0;
            int i = start + count - 1;

            do 
            {
                measureSize += (definitions[i].SizeType == LayoutTimeSizeType.Auto) 
                    ? definitions[i].MinSize 
                    : definitions[i].MeasureSize;
            } while (--i >= start); 

            return (measureSize);
        }
 
        /// 
        /// Accumulates length type information for given definition's range. 
        ///  
        /// Source array of definitions to read values from.
        /// Starting index of the range. 
        /// Number of definitions included in the range.
        /// Length type for given range.
        private LayoutTimeSizeType GetLengthTypeForRange(
            DefinitionBase[] definitions, 
            int start,
            int count) 
        { 
            Debug.Assert(0 < count && 0 <= start && (start + count) <= definitions.Length);
 
            LayoutTimeSizeType lengthType = LayoutTimeSizeType.None;
            int i = start + count - 1;

            do 
            {
                lengthType |= definitions[i].SizeType; 
            } while (--i >= start); 

            return (lengthType); 
        }

        /// 
        /// Distributes min size back to definition array's range. 
        /// 
        /// Start of the range. 
        /// Number of items in the range. 
        /// Minimum size that should "fit" into the definitions range.
        /// Definition array receiving distribution. 
        /// Size used to resolve percentages.
        private void EnsureMinSizeInDefinitionRange(
            DefinitionBase[] definitions,
            int start, 
            int count,
            double requestedSize, 
            double percentReferenceSize) 
        {
            Debug.Assert(1 < count && 0 <= start && (start + count) <= definitions.Length); 

            //  avoid processing when asked to distribute "0"
            if (!_IsZero(requestedSize))
            { 
                DefinitionBase[] tempDefinitions = TempDefinitions; //  temp array used to remember definitions for sorting
                int end = start + count; 
                int autoDefinitionsCount = 0; 
                double rangeMinSize = 0;
                double rangePreferredSize = 0; 
                double rangeMaxSize = 0;
                double maxMaxSize = 0;                              //  maximum of maximum sizes

                //  first accumulate the necessary information: 
                //  a) sum up the sizes in the range;
                //  b) count the number of auto definitions in the range; 
                //  c) initialize temp array 
                //  d) cache the maximum size into SizeCache
                //  e) accumulate max of max sizes 
                for (int i = start; i < end; ++i)
                {
                    double minSize = definitions[i].MinSize;
                    double preferredSize = definitions[i].PreferredSize; 
                    double maxSize = Math.Max(definitions[i].UserMaxSize, minSize);
 
                    rangeMinSize += minSize; 
                    rangePreferredSize += preferredSize;
                    rangeMaxSize += maxSize; 

                    definitions[i].SizeCache = maxSize;

                    //  sanity check: no matter what, but min size must always be the smaller; 
                    //  max size must be the biggest; and preferred should be in between
                    Debug.Assert(   minSize <= preferredSize 
                                &&  preferredSize <= maxSize 
                                &&  rangeMinSize <= rangePreferredSize
                                &&  rangePreferredSize <= rangeMaxSize  ); 

                    if (maxMaxSize < maxSize)   maxMaxSize = maxSize;
                    if (definitions[i].UserSize.IsAuto) autoDefinitionsCount++;
                    tempDefinitions[i - start] = definitions[i]; 
                }
 
                //  avoid processing if the range already big enough 
                if (requestedSize > rangeMinSize)
                { 
                    if (requestedSize <= rangePreferredSize)
                    {
                        //
                        //  requestedSize fits into preferred size of the range. 
                        //  distribute according to the following logic:
                        //  * do not distribute into auto definitions - they should continue to stay "tight"; 
                        //  * for all non-auto definitions distribute to equi-size min sizes, without exceeding preferred size. 
                        //
                        //  in order to achieve that, definitions are sorted in a way that all auto definitions 
                        //  are first, then definitions follow ascending order with PreferredSize as the key of sorting.
                        //
                        double sizeToDistribute;
                        int i; 

                        Array.Sort(tempDefinitions, 0, count, s_spanPreferredDistributionOrderComparer); 
                        for (i = 0, sizeToDistribute = requestedSize; i < autoDefinitionsCount; ++i) 
                        {
                            //  sanity check: only auto definitions allowed in this loop 
                            Debug.Assert(tempDefinitions[i].UserSize.IsAuto);

                            //  adjust sizeToDistribute value by subtracting auto definition min size
                            sizeToDistribute -= (tempDefinitions[i].MinSize); 
                        }
 
                        for (; i < count; ++i) 
                        {
                            //  sanity check: no auto definitions allowed in this loop 
                            Debug.Assert(!tempDefinitions[i].UserSize.IsAuto);

                            double newMinSize = Math.Min(sizeToDistribute / (count - i), tempDefinitions[i].PreferredSize);
                            if (newMinSize > tempDefinitions[i].MinSize) { tempDefinitions[i].UpdateMinSize(newMinSize); } 
                            sizeToDistribute -= newMinSize;
                        } 
 
                        //  sanity check: requested size must all be distributed
                        Debug.Assert(_IsZero(sizeToDistribute)); 
                    }
                    else if (requestedSize <= rangeMaxSize)
                    {
                        // 
                        //  requestedSize bigger than preferred size, but fit into max size of the range.
                        //  distribute according to the following logic: 
                        //  * do not distribute into auto definitions, if possible - they should continue to stay "tight"; 
                        //  * for all non-auto definitions distribute to euqi-size min sizes, without exceeding max size.
                        // 
                        //  in order to achieve that, definitions are sorted in a way that all non-auto definitions
                        //  are last, then definitions follow ascending order with MaxSize as the key of sorting.
                        //
                        double sizeToDistribute; 
                        int i;
 
                        Array.Sort(tempDefinitions, 0, count, s_spanMaxDistributionOrderComparer); 
                        for (i = 0, sizeToDistribute = requestedSize - rangePreferredSize; i < count - autoDefinitionsCount; ++i)
                        { 
                            //  sanity check: no auto definitions allowed in this loop
                            Debug.Assert(!tempDefinitions[i].UserSize.IsAuto);

                            double preferredSize = tempDefinitions[i].PreferredSize; 
                            double newMinSize = preferredSize + sizeToDistribute / (count - autoDefinitionsCount - i);
                            tempDefinitions[i].UpdateMinSize(Math.Min(newMinSize, tempDefinitions[i].SizeCache)); 
                            sizeToDistribute -= (tempDefinitions[i].MinSize - preferredSize); 
                        }
 
                        for (; i < count; ++i)
                        {
                            //  sanity check: only auto definitions allowed in this loop
                            Debug.Assert(tempDefinitions[i].UserSize.IsAuto); 

                            double preferredSize = tempDefinitions[i].MinSize; 
                            double newMinSize = preferredSize + sizeToDistribute / (count - i); 
                            tempDefinitions[i].UpdateMinSize(Math.Min(newMinSize, tempDefinitions[i].SizeCache));
                            sizeToDistribute -= (tempDefinitions[i].MinSize - preferredSize); 
                        }

                        //  sanity check: requested size must all be distributed
                        Debug.Assert(_IsZero(sizeToDistribute)); 
                    }
                    else 
                    { 
                        //
                        //  requestedSize bigger than max size of the range. 
                        //  distribute according to the following logic:
                        //  * for all definitions distribute to equi-size min sizes.
                        //
                        double equalSize = requestedSize / count; 

                        if (    equalSize < maxMaxSize 
                            &&  !_AreClose(equalSize, maxMaxSize)   ) 
                        {
                            //  equi-size is less than maximum of maxSizes. 
                            //  in this case distribute so that smaller definitions grow faster than
                            //  bigger ones.
                            double totalRemainingSize = maxMaxSize * count - rangeMaxSize;
                            double sizeToDistribute = requestedSize - rangeMaxSize; 

                            //  sanity check: totalRemainingSize and sizeToDistribute must be real positive numbers 
                            Debug.Assert(   !double.IsInfinity(totalRemainingSize) 
                                        &&  !DoubleUtil.IsNaN(totalRemainingSize)
                                        &&  totalRemainingSize > 0 
                                        &&  !double.IsInfinity(sizeToDistribute)
                                        &&  !DoubleUtil.IsNaN(sizeToDistribute)
                                        &&  sizeToDistribute > 0    );
 
                            for (int i = 0; i < count; ++i)
                            { 
                                double deltaSize = (maxMaxSize - tempDefinitions[i].SizeCache) * sizeToDistribute / totalRemainingSize; 
                                tempDefinitions[i].UpdateMinSize(tempDefinitions[i].SizeCache + deltaSize);
                            } 
                        }
                        else
                        {
                            // 
                            //  equi-size is greater or equal to maximum of max sizes.
                            //  all definitions receive equalSize as their mim sizes. 
                            // 
                            for (int i = 0; i < count; ++i)
                            { 
                                tempDefinitions[i].UpdateMinSize(equalSize);
                            }
                        }
                    } 
                }
            } 
        } 

        ///  
        /// Resolves Star's for given array of definitions.
        /// 
        /// Array of definitions to resolve stars.
        /// All available size. 
        /// 
        /// Must initialize LayoutSize for all Star entries in given array of definitions. 
        ///  
        private void ResolveStar(
            DefinitionBase[] definitions, 
            double availableSize)
        {
            DefinitionBase[] tempDefinitions = TempDefinitions;
            int starDefinitionsCount = 0; 
            double takenSize = 0;
 
            for (int i = 0; i < definitions.Length; ++i) 
            {
                switch (definitions[i].SizeType) 
                {
                    case (LayoutTimeSizeType.Auto):
                        takenSize += definitions[i].MinSize;
                        break; 
                    case (LayoutTimeSizeType.Pixel):
                        takenSize += definitions[i].MeasureSize; 
                        break; 
                    case (LayoutTimeSizeType.Star):
                        { 
                            tempDefinitions[starDefinitionsCount++] = definitions[i];

                            double starValue = definitions[i].UserSize.Value;
 
                            if (_IsZero(starValue))
                            { 
                                definitions[i].MeasureSize = 0; 
                                definitions[i].SizeCache = 0;
                            } 
                            else
                            {
                                //  clipping by c_starClip guarantees that sum of even a very big number of max'ed out star values
                                //  can be summed up without overflow 
                                starValue = Math.Min(starValue, c_starClip);
 
                                //  Note: normalized star value is temporary cached into MeasureSize 
                                definitions[i].MeasureSize = starValue;
                                double maxSize             = Math.Max(definitions[i].MinSize, definitions[i].UserMaxSize); 
                                maxSize                    = Math.Min(maxSize, c_starClip);
                                definitions[i].SizeCache   = maxSize / starValue;
                            }
                        } 
                        break;
                } 
            } 

            if (starDefinitionsCount > 0) 
            {
                Array.Sort(tempDefinitions, 0, starDefinitionsCount, s_starDistributionOrderComparer);

                //  the 'do {} while' loop below calculates sum of star weights in order to avoid fp overflow... 
                //  partial sum value is stored in each definition's SizeCache member.
                //  this way the algorithm guarantees (starValue <= definition.SizeCache) and thus 
                //  (starValue / definition.SizeCache) will never overflow due to sum of star weights becoming zero. 
                //  this is an important change from previous implementation where the following was possible:
                //  ((BigValueStar + SmallValueStar) - BigValueStar) resulting in 0... 
                double allStarWeights = 0;
                int i = starDefinitionsCount - 1;
                do
                { 
                    allStarWeights += tempDefinitions[i].MeasureSize;
                    tempDefinitions[i].SizeCache = allStarWeights; 
                } while (--i >= 0); 

                i = 0; 
                do
                {
                    double resolvedSize;
                    double starValue = tempDefinitions[i].MeasureSize; 

                    if (_IsZero(starValue)) 
                    { 
                        resolvedSize = tempDefinitions[i].MinSize;
                    } 
                    else
                    {
                        double userSize = Math.Max(availableSize - takenSize, 0.0) * (starValue / tempDefinitions[i].SizeCache);
                        resolvedSize    = Math.Min(userSize, tempDefinitions[i].UserMaxSize); 
                        resolvedSize    = Math.Max(tempDefinitions[i].MinSize, resolvedSize);
                    } 
 
                    tempDefinitions[i].MeasureSize = resolvedSize;
                    takenSize                     += resolvedSize; 
                } while (++i < starDefinitionsCount);
            }
        }
 
        /// 
        /// Calculates desired size for given array of definitions. 
        ///  
        /// Array of definitions to use for calculations.
        /// Desired size. 
        private double CalculateDesiredSize(
            DefinitionBase[] definitions)
        {
            double desiredSize = 0; 

            for (int i = 0; i < definitions.Length; ++i) 
            { 
                desiredSize += definitions[i].MinSize;
            } 

            return (desiredSize);
        }
 
        /// 
        /// Calculates and sets final size for all definitions in the given array. 
        ///  
        /// Array of definitions to process.
        /// Final size to lay out to. 
        /// True if sizing row definitions, false for columns
        private void SetFinalSize(
            DefinitionBase[] definitions,
            double finalSize, 
            bool columns)
        { 
            int starDefinitionsCount = 0;                       //  traverses form the first entry up 
            int nonStarIndex = definitions.Length;              //  traverses from the last entry down
            double allPreferredArrangeSize = 0; 
            bool useLayoutRounding = this.UseLayoutRounding;
            int[] definitionIndices = DefinitionIndices;
            double[] roundingErrors = null;
 
            // If using layout rounding, check whether rounding needs to compensate for high DPI
            double dpi = 1.0; 
 
            if (useLayoutRounding)
            { 
                dpi = columns ? FrameworkElement.DpiScaleX : FrameworkElement.DpiScaleY;
                roundingErrors = RoundingErrors;
            }
 
            for (int i = 0; i < definitions.Length; ++i)
            { 
                //  if definition is shared then is cannot be star 
                Debug.Assert(!definitions[i].IsShared || !definitions[i].UserSize.IsStar);
 
                if (definitions[i].UserSize.IsStar)
                {
                    double starValue = definitions[i].UserSize.Value;
 
                    if (_IsZero(starValue))
                    { 
                        //  cach normilized star value temporary into MeasureSize 
                        definitions[i].MeasureSize = 0;
                        definitions[i].SizeCache = 0; 
                    }
                    else
                    {
                        //  clipping by c_starClip guarantees that sum of even a very big number of max'ed out star values 
                        //  can be summed up without overflow
                        starValue = Math.Min(starValue, c_starClip); 
 
                        //  Note: normalized star value is temporary cached into MeasureSize
                        definitions[i].MeasureSize = starValue; 
                        double maxSize = Math.Max(definitions[i].MinSizeForArrange, definitions[i].UserMaxSize);
                        maxSize = Math.Min(maxSize, c_starClip);
                        definitions[i].SizeCache = maxSize / starValue;
                        if (useLayoutRounding) 
                        {
                            roundingErrors[i] = definitions[i].SizeCache; 
                            definitions[i].SizeCache = UIElement.RoundLayoutValue(definitions[i].SizeCache, dpi); 
                        }
                    } 
                    definitionIndices[starDefinitionsCount++] = i;
                }
                else
                { 
                    double userSize = 0;
 
                    switch (definitions[i].UserSize.GridUnitType) 
                    {
                        case (GridUnitType.Pixel): 
                            userSize = definitions[i].UserSize.Value;
                            break;

                        case (GridUnitType.Auto): 
                            userSize = definitions[i].MinSizeForArrange;
                            break; 
                    } 

                    double userMaxSize; 

                    if (definitions[i].IsShared)
                    {
                        //  overriding userMaxSize 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. 
                        userMaxSize = userSize;
                    } 
                    else
                    {
                        userMaxSize = definitions[i].UserMaxSize;
                    } 

                    definitions[i].SizeCache = Math.Max(definitions[i].MinSizeForArrange, Math.Min(userSize, userMaxSize)); 
                    if (useLayoutRounding) 
                    {
                        roundingErrors[i] = definitions[i].SizeCache; 
                        definitions[i].SizeCache = UIElement.RoundLayoutValue(definitions[i].SizeCache, dpi);
                    }

                    allPreferredArrangeSize += definitions[i].SizeCache; 
                    definitionIndices[--nonStarIndex] = i;
                } 
            } 

            //  indices should meet 
            Debug.Assert(nonStarIndex == starDefinitionsCount);

            if (starDefinitionsCount > 0)
            { 
                StarDistributionOrderIndexComparer starDistributionOrderIndexComparer = new StarDistributionOrderIndexComparer(definitions);
                Array.Sort(definitionIndices, 0, starDefinitionsCount, starDistributionOrderIndexComparer); 
 
                //  the 'do {} while' loop below calculates sum of star weights in order to avoid fp overflow...
                //  partial sum value is stored in each definition's SizeCache member. 
                //  this way the algorithm guarantees (starValue <= definition.SizeCache) and thus
                //  (starValue / definition.SizeCache) will never overflow due to sum of star weights becoming zero.
                //  this is an important change from previous implementation where the following was possible:
                //  ((BigValueStar + SmallValueStar) - BigValueStar) resulting in 0... 
                double allStarWeights = 0;
                int i = starDefinitionsCount - 1; 
                do 
                {
                    allStarWeights += definitions[definitionIndices[i]].MeasureSize; 
                    definitions[definitionIndices[i]].SizeCache = allStarWeights;
                } while (--i >= 0);

                i = 0; 
                do
                { 
                    double resolvedSize; 
                    double starValue = definitions[definitionIndices[i]].MeasureSize;
 
                    if (_IsZero(starValue))
                    {
                        resolvedSize = definitions[definitionIndices[i]].MinSizeForArrange;
                    } 
                    else
                    { 
                        double userSize = Math.Max(finalSize - allPreferredArrangeSize, 0.0) * (starValue / definitions[definitionIndices[i]].SizeCache); 
                        resolvedSize = Math.Min(userSize, definitions[definitionIndices[i]].UserMaxSize);
                        resolvedSize = Math.Max(definitions[definitionIndices[i]].MinSizeForArrange, resolvedSize); 
                    }

                    definitions[definitionIndices[i]].SizeCache = resolvedSize;
                    if (useLayoutRounding) 
                    {
                        roundingErrors[definitionIndices[i]] = definitions[definitionIndices[i]].SizeCache; 
                        definitions[definitionIndices[i]].SizeCache = UIElement.RoundLayoutValue(definitions[definitionIndices[i]].SizeCache, dpi); 
                    }
 
                    allPreferredArrangeSize += definitions[definitionIndices[i]].SizeCache;
                } while (++i < starDefinitionsCount);
            }
 
            if (    allPreferredArrangeSize > finalSize
                &&  !_AreClose(allPreferredArrangeSize, finalSize)  ) 
            { 
                DistributionOrderIndexComparer distributionOrderIndexComparer = new DistributionOrderIndexComparer(definitions);
                Array.Sort(definitionIndices, 0, definitions.Length, distributionOrderIndexComparer); 
                double sizeToDistribute = finalSize - allPreferredArrangeSize;

                for (int i = 0; i < definitions.Length; ++i)
                { 
                    int definitionIndex = definitionIndices[i];
                    double final = definitions[definitionIndex].SizeCache + (sizeToDistribute / (definitions.Length - i)); 
                    double finalOld = final; 
                    final = Math.Max(final, definitions[definitionIndex].MinSizeForArrange);
                    final = Math.Min(final, definitions[definitionIndex].SizeCache); 

                    if (useLayoutRounding)
                    {
                        roundingErrors[definitionIndex] = final; 
                        final = UIElement.RoundLayoutValue(finalOld, dpi);
                        final = Math.Max(final, definitions[definitionIndex].MinSizeForArrange); 
                        final = Math.Min(final, definitions[definitionIndex].SizeCache); 
                    }
 
                    sizeToDistribute -= (final - definitions[definitionIndex].SizeCache);
                    definitions[definitionIndex].SizeCache = final;
                }
 
                allPreferredArrangeSize = finalSize - sizeToDistribute;
            } 
 
            if (useLayoutRounding)
            { 
                if (!_AreClose(allPreferredArrangeSize, finalSize))
                {
                    // Compute deltas
                    for (int i = 0; i < definitions.Length; ++i) 
                    {
                        roundingErrors[i] = roundingErrors[i] - definitions[i].SizeCache; 
                        definitionIndices[i] = i; 
                    }
 
                    // Sort rounding errors
                    RoundingErrorIndexComparer roundingErrorIndexComparer = new RoundingErrorIndexComparer(roundingErrors);
                    Array.Sort(definitionIndices, 0, definitions.Length, roundingErrorIndexComparer);
                    double adjustedSize = allPreferredArrangeSize; 
                    double dpiIncrement = UIElement.RoundLayoutValue(1.0, dpi);
 
                    if (allPreferredArrangeSize > finalSize) 
                    {
                        int i = definitions.Length - 1; 
                        while ((adjustedSize > finalSize && !_AreClose(adjustedSize, finalSize)) && i >= 0)
                        {
                            DefinitionBase definition = definitions[definitionIndices[i]];
                            double final = definition.SizeCache - dpiIncrement; 
                            final = Math.Max(final, definition.MinSizeForArrange);
                            if (final < definition.SizeCache) 
                            { 
                                adjustedSize -= dpiIncrement;
                            } 
                            definition.SizeCache = final;
                            i--;
                        }
                    } 
                    else if (allPreferredArrangeSize < finalSize)
                    { 
                        int i = 0; 
                        while ((adjustedSize < finalSize && !_AreClose(adjustedSize, finalSize)) && i < definitions.Length)
                        { 
                            DefinitionBase definition = definitions[definitionIndices[i]];
                            double final = definition.SizeCache + dpiIncrement;
                            final = Math.Max(final, definition.MinSizeForArrange);
                            if (final > definition.SizeCache) 
                            {
                                adjustedSize += dpiIncrement; 
                            } 
                            definition.SizeCache = final;
                            i++; 
                        }
                    }
                }
            } 

            definitions[0].FinalOffset = 0.0; 
            for (int i = 0; i < definitions.Length; ++i) 
            {
                definitions[(i + 1) % definitions.Length].FinalOffset = definitions[i].FinalOffset + definitions[i].SizeCache; 
            }
        }

        ///  
        /// Sorts row/column indices by rounding error if layout rounding is applied.
        ///  
        /// Index, rounding error pair 
        /// Index, rounding error pair
        /// 1 if x.Value > y.Value, 0 if equal, -1 otherwise 
        private static int CompareRoundingErrors(KeyValuePair x, KeyValuePair y)
        {
            if (x.Value < y.Value)
            { 
                return -1;
            } 
            else if (x.Value > y.Value) 
            {
                return 1; 
            }
            return 0;
        }
 
        /// 
        /// Calculates final (aka arrange) size for given range. 
        ///  
        /// Array of definitions to process.
        /// Start of the range. 
        /// Number of items in the range.
        /// Final size.
        private double GetFinalSizeForRange(
            DefinitionBase[] definitions, 
            int start,
            int count) 
        { 
            double size = 0;
            int i = start + count - 1; 

            do
            {
                size += definitions[i].SizeCache; 
            } while (--i >= start);
 
            return (size); 
        }
 
        /// 
        /// Clears dirty state for the grid and its columns / rows
        /// 
        private void SetValid() 
        {
            ExtendedData extData = ExtData; 
            if (extData != null) 
            {
//                for (int i = 0; i < PrivateColumnCount; ++i) DefinitionsU[i].SetValid (); 
//                for (int i = 0; i < PrivateRowCount; ++i) DefinitionsV[i].SetValid ();

                if (extData.TempDefinitions != null)
                { 
                    //  TempDefinitions has to be cleared to avoid "memory leaks"
                    Array.Clear(extData.TempDefinitions, 0, Math.Max(DefinitionsU.Length, DefinitionsV.Length)); 
                    extData.TempDefinitions = null; 
                }
            } 
        }

        /// 
        /// Returns true if ColumnDefinitions collection is not empty 
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)] 
        public bool ShouldSerializeColumnDefinitions() 
        {
            ExtendedData extData = ExtData; 
            return (    extData != null
                    &&  extData.ColumnDefinitions != null
                    &&  extData.ColumnDefinitions.Count > 0   );
        } 

        ///  
        /// Returns true if RowDefinitions collection is not empty 
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)] 
        public bool ShouldSerializeRowDefinitions()
        {
            ExtendedData extData = ExtData;
            return (    extData != null 
                    &&  extData.RowDefinitions != null
                    &&  extData.RowDefinitions.Count > 0  ); 
        } 

        ///  
        /// Synchronized ShowGridLines property with the state of the grid's visual collection
        /// by adding / removing GridLinesRenderer visual.
        /// Returns a reference to GridLinesRenderer visual or null.
        ///  
        private GridLinesRenderer EnsureGridLinesRenderer()
        { 
            // 
            //  synchronize the state
            // 
            if (ShowGridLines && (_gridLinesRenderer == null))
            {
                _gridLinesRenderer = new GridLinesRenderer();
                this.AddVisualChild(_gridLinesRenderer); 
            }
 
            if ((!ShowGridLines) && (_gridLinesRenderer != null)) 
            {
                this.RemoveVisualChild(_gridLinesRenderer); 
                _gridLinesRenderer = null;
            }

            return (_gridLinesRenderer); 
        }
 
        ///  
        /// 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); 
        }
 
        ///  
        /// CheckFlagsOr returns true if at least one flag in the
        /// given bitmask is set. 
        /// 
        /// 
        /// If no bits are set in the given bitmask, the method returns
        /// true. 
        /// 
        private bool CheckFlagsOr(Flags flags) 
        { 
            return (flags == 0 || (_flags & flags) != 0);
        } 

        /// 
        /// 
        ///  
        private static void OnShowGridLinesPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            Grid grid = (Grid)d; 

            if (    grid.ExtData != null    // trivial grid is 1 by 1. there is no grid lines anyway 
                &&  grid.ListenToNotifications)
            {
                grid.InvalidateVisual();
            } 

            grid.SetFlags((bool) e.NewValue, Flags.ShowGridLinesPropertyValue); 
        } 

        ///  
        /// 
        /// 
        private static void OnCellAttachedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            Visual child = d as Visual;
 
            if (child != null) 
            {
                Grid grid = VisualTreeHelper.GetParent(child) as Grid; 
                if (    grid != null
                    &&  grid.ExtData != null
                    &&  grid.ListenToNotifications  )
                { 
                    grid.CellsStructureDirty = true;
                    grid.InvalidateMeasure(); 
                } 
            }
        } 

        /// 
        /// 
        ///  
        private static bool IsIntValueNotNegative(object value)
        { 
            return ((int)value >= 0); 
        }
 
        /// 
        /// 
        /// 
        private static bool IsIntValueGreaterThanZero(object value) 
        {
            return ((int)value > 0); 
        } 

        ///  
        /// Helper for Comparer methods.
        /// 
        /// 
        /// true iff one or both of x and y are null, in which case result holds 
        /// the relative sort order.
        ///  
        private static bool CompareNullRefs(object x, object y, out int result) 
        {
            result = 2; 

            if (x == null)
            {
                if (y == null) 
                {
                    result = 0; 
                } 
                else
                { 
                    result = -1;
                }
            }
            else 
            {
                if (y == null) 
                { 
                    result = 1;
                } 
            }

            return (result != 2);
        } 

        #endregion Private Methods 
 
        //------------------------------------------------------
        // 
        //  Private Properties
        //
        //-----------------------------------------------------
 
        #region Private Properties
 
        ///  
        /// Private version returning array of column definitions.
        ///  
        private DefinitionBase[] DefinitionsU
        {
            get { return (ExtData.DefinitionsU); }
        } 

        ///  
        /// Private version returning array of row definitions. 
        /// 
        private DefinitionBase[] DefinitionsV 
        {
            get { return (ExtData.DefinitionsV); }
        }
 
        /// 
        /// Helper accessor to layout time array of definitions. 
        ///  
        private DefinitionBase[] TempDefinitions
        { 
            get
            {
                ExtendedData extData = ExtData;
 
                if (extData.TempDefinitions == null)
                { 
                    int requiredLength = Math.Max(DefinitionsU.Length, DefinitionsV.Length); 
                    WeakReference tempDefinitionsWeakRef = (WeakReference)Thread.GetData(s_tempDefinitionsDataSlot);
                    if (tempDefinitionsWeakRef == null) 
                    {
                        extData.TempDefinitions = new DefinitionBase[requiredLength * 2];
                        Thread.SetData(s_tempDefinitionsDataSlot, new WeakReference(extData.TempDefinitions));
                    } 
                    else
                    { 
                        extData.TempDefinitions = (DefinitionBase[])tempDefinitionsWeakRef.Target; 
                        if (    extData.TempDefinitions == null
                            ||  extData.TempDefinitions.Length < requiredLength   ) 
                        {
                            extData.TempDefinitions = new DefinitionBase[requiredLength * 2];
                            tempDefinitionsWeakRef.Target = extData.TempDefinitions;
                        } 
                    }
                } 
                return (extData.TempDefinitions); 
            }
        } 

        /// 
        /// Helper accessor to definition indices.
        ///  
        private int[] DefinitionIndices
        { 
            get 
            {
                int requiredLength = Math.Max(DefinitionsU.Length, DefinitionsV.Length); 

                if (_definitionIndices == null && requiredLength == 0)
                {
                    _definitionIndices = new int[1]; 
                }
                else if (_definitionIndices == null || _definitionIndices.Length < requiredLength) 
                { 
                    _definitionIndices = new int[requiredLength];
                } 

                return _definitionIndices;
            }
        } 

        ///  
        /// Helper accessor to rounding errors. 
        /// 
        private double[] RoundingErrors 
        {
            get
            {
                int requiredLength = Math.Max(DefinitionsU.Length, DefinitionsV.Length); 

                if (_roundingErrors == null && requiredLength == 0) 
                { 
                    _roundingErrors = new double[1];
                } 
                else if (_roundingErrors == null || _roundingErrors.Length < requiredLength)
                {
                    _roundingErrors = new double[requiredLength];
                } 
                return _roundingErrors;
            } 
        } 

        ///  
        /// Private version returning array of cells.
        /// 
        private CellCache[] PrivateCells
        { 
            get { return (ExtData.CellCachesCollection); }
        } 
 
        /// 
        /// Convenience accessor to ValidCellsStructure bit flag. 
        /// 
        private bool CellsStructureDirty
        {
            get { return (!CheckFlagsAnd(Flags.ValidCellsStructure)); } 
            set { SetFlags(!value, Flags.ValidCellsStructure); }
        } 
 
        /// 
        /// Convenience accessor to ListenToNotifications bit flag. 
        /// 
        private bool ListenToNotifications
        {
            get { return (CheckFlagsAnd(Flags.ListenToNotifications)); } 
            set { SetFlags(value, Flags.ListenToNotifications); }
        } 
 
        /// 
        /// Convenience accessor to SizeToContentU bit flag. 
        /// 
        private bool SizeToContentU
        {
            get { return (CheckFlagsAnd(Flags.SizeToContentU)); } 
            set { SetFlags(value, Flags.SizeToContentU); }
        } 
 
        /// 
        /// Convenience accessor to SizeToContentV bit flag. 
        /// 
        private bool SizeToContentV
        {
            get { return (CheckFlagsAnd(Flags.SizeToContentV)); } 
            set { SetFlags(value, Flags.SizeToContentV); }
        } 
 
        /// 
        /// Convenience accessor to HasStarCellsU bit flag. 
        /// 
        private bool HasStarCellsU
        {
            get { return (CheckFlagsAnd(Flags.HasStarCellsU)); } 
            set { SetFlags(value, Flags.HasStarCellsU); }
        } 
 
        /// 
        /// Convenience accessor to HasStarCellsV bit flag. 
        /// 
        private bool HasStarCellsV
        {
            get { return (CheckFlagsAnd(Flags.HasStarCellsV)); } 
            set { SetFlags(value, Flags.HasStarCellsV); }
        } 
 
        /// 
        /// Convenience accessor to HasGroup3CellsInAutoRows bit flag. 
        /// 
        private bool HasGroup3CellsInAutoRows
        {
            get { return (CheckFlagsAnd(Flags.HasGroup3CellsInAutoRows)); } 
            set { SetFlags(value, Flags.HasGroup3CellsInAutoRows); }
        } 
 
        /// 
        /// fp version of d == 0. 
        /// 
        /// Value to check.
        /// true if d == 0.
        private static bool _IsZero(double d) 
        {
            return (Math.Abs(d) < c_epsilon); 
        } 

        ///  
        /// fp version of d1 == d2
        /// 
        /// First value to compare
        /// Second value to compare 
        /// true if d1 == d2
        private static bool _AreClose(double d1, double d2) 
        { 
            return (Math.Abs(d1 - d2) < c_epsilon);
        } 

        /// 
        /// Returns reference to extended data bag.
        ///  
        private ExtendedData ExtData
        { 
            get { return (_data); } 
        }
 
        #endregion Private Properties

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

        #region Private Fields 
        private ExtendedData _data;                             //  extended data instantiated on demand, for non-trivial case handling only
        private Flags _flags;                                   //  grid validity / property caches dirtiness flags
        private GridLinesRenderer _gridLinesRenderer;
 
        // Keeps track of definition indices.
        int[] _definitionIndices; 
 
        // Stores unrounded values and rounding errors during layout rounding.
        double[] _roundingErrors; 

        #endregion Private Fields

        //----------------------------------------------------- 
        //
        //  Static Fields 
        // 
        //-----------------------------------------------------
 
        #region Static Fields
        private const double c_epsilon = 1e-5;                  //  used in fp calculations
        private const double c_starClip = 1e298;                //  used as maximum for clipping star values during normalization
        private static readonly LocalDataStoreSlot s_tempDefinitionsDataSlot = Thread.AllocateDataSlot(); 
        private static readonly IComparer s_spanPreferredDistributionOrderComparer = new SpanPreferredDistributionOrderComparer();
        private static readonly IComparer s_spanMaxDistributionOrderComparer = new SpanMaxDistributionOrderComparer(); 
        private static readonly IComparer s_starDistributionOrderComparer = new StarDistributionOrderComparer(); 
        private static readonly IComparer s_distributionOrderComparer = new DistributionOrderComparer();
 
        #endregion Static Fields

        //------------------------------------------------------
        // 
        //  Private Structures / Classes
        // 
        //----------------------------------------------------- 

        #region Private Structures Classes 

        /// 
        /// Extended data instantiated on demand, when grid handles non-trivial case.
        ///  
        private class ExtendedData
        { 
            internal ColumnDefinitionCollection ColumnDefinitions;  //  collection of column definitions (logical tree support) 
            internal RowDefinitionCollection RowDefinitions;        //  collection of row definitions (logical tree support)
            internal DefinitionBase[] DefinitionsU;                 //  collection of column definitions used during calc 
            internal DefinitionBase[] DefinitionsV;                 //  collection of row definitions used during calc
            internal CellCache[] CellCachesCollection;              //  backing store for logical children
            internal int CellGroup1;                                //  index of the first cell in first cell group
            internal int CellGroup2;                                //  index of the first cell in second cell group 
            internal int CellGroup3;                                //  index of the first cell in third cell group
            internal int CellGroup4;                                //  index of the first cell in forth cell group 
            internal DefinitionBase[] TempDefinitions;              //  temporary array used during layout for various purposes 
                                                                    //  TempDefinitions.Length == Max(definitionsU.Length, definitionsV.Length)
        } 

        /// 
        /// Grid validity / property caches dirtiness flags
        ///  
        [System.Flags]
        private enum Flags 
        { 
            //
            //  the foolowing flags let grid tracking dirtiness in more granular manner: 
            //  * Valid???Structure flags indicate that elements were added or removed.
            //  * Valid???Layout flags indicate that layout time portion of the information
            //    stored on the objects should be updated.
            // 
            ValidDefinitionsUStructure              = 0x00000001,
            ValidDefinitionsVStructure              = 0x00000002, 
            ValidCellsStructure                     = 0x00000004, 

            // 
            //  boolean properties state
            //
            ShowGridLinesPropertyValue              = 0x00000100,   //  show grid lines ?
 
            //
            //  boolean flags 
            // 
            ListenToNotifications                   = 0x00001000,   //  "0" when all notifications are ignored
            SizeToContentU                          = 0x00002000,   //  "1" if calculating to content in U direction 
            SizeToContentV                          = 0x00004000,   //  "1" if calculating to content in V direction
            HasStarCellsU                           = 0x00008000,   //  "1" if at least one cell belongs to a Star column
            HasStarCellsV                           = 0x00010000,   //  "1" if at least one cell belongs to a Star row
            HasGroup3CellsInAutoRows                = 0x00020000,   //  "1" if at least one cell of group 3 belongs to an Auto row 
            MeasureOverrideInProgress               = 0x00040000,   //  "1" while in the context of Grid.MeasureOverride
            ArrangeOverrideInProgress               = 0x00080000,   //  "1" while in the context of Grid.ArrangeOverride 
        } 

        #endregion Private Structures Classes 

        //------------------------------------------------------
        //
        //  Properties 
        //
        //------------------------------------------------------ 
 
        #region Properties
 
        /// 
        /// ShowGridLines property. This property is used mostly
        /// for simplification of visual debuggig. When it is set
        /// to true grid lines are drawn to visualize location 
        /// of grid lines.
        ///  
        public static readonly DependencyProperty ShowGridLinesProperty = 
                DependencyProperty.Register(
                      "ShowGridLines", 
                      typeof(bool),
                      typeof(Grid),
                      new FrameworkPropertyMetadata(
                              false, 
                              new PropertyChangedCallback(OnShowGridLinesPropertyChanged)));
 
        ///  
        /// Column property. This is an attached property.
        /// Grid defines Column property, so that it can be set 
        /// on any element treated as a cell. Column property
        /// specifies child's position with respect to columns.
        /// 
        ///  
        ///  Columns are 0 - based. In order to appear in first column, element
        /// should have Column property set to 0.  
        ///  Default value for the property is 0.  
        /// 
        [CommonDependencyProperty] 
        public static readonly DependencyProperty ColumnProperty =
                DependencyProperty.RegisterAttached(
                      "Column",
                      typeof(int), 
                      typeof(Grid),
                      new FrameworkPropertyMetadata( 
                              0, 
                              new PropertyChangedCallback(OnCellAttachedPropertyChanged)),
                      new ValidateValueCallback(IsIntValueNotNegative)); 

        /// 
        /// Row property. This is an attached property.
        /// Grid defines Row, so that it can be set 
        /// on any element treated as a cell. Row property
        /// specifies child's position with respect to rows. 
        ///  
        ///  Rows are 0 - based. In order to appear in first row, element
        /// should have Row property set to 0.  
        ///  Default value for the property is 0. 
        /// 
        /// 
        [CommonDependencyProperty] 
        public static readonly DependencyProperty RowProperty =
                DependencyProperty.RegisterAttached( 
                      "Row", 
                      typeof(int),
                      typeof(Grid), 
                      new FrameworkPropertyMetadata(
                              0,
                              new PropertyChangedCallback(OnCellAttachedPropertyChanged)),
                      new ValidateValueCallback(IsIntValueNotNegative)); 

        ///  
        /// ColumnSpan property. This is an attached property. 
        /// Grid defines ColumnSpan, so that it can be set
        /// on any element treated as a cell. ColumnSpan property 
        /// specifies child's width with respect to columns.
        /// Example, ColumnSpan == 2 means that child will span across two columns.
        /// 
        ///  
        /// Default value for the property is 1.
        ///  
        [CommonDependencyProperty] 
        public static readonly DependencyProperty ColumnSpanProperty =
                DependencyProperty.RegisterAttached( 
                      "ColumnSpan",
                      typeof(int),
                      typeof(Grid),
                      new FrameworkPropertyMetadata( 
                              1,
                              new PropertyChangedCallback(OnCellAttachedPropertyChanged)), 
                      new ValidateValueCallback(IsIntValueGreaterThanZero)); 

        ///  
        /// RowSpan property. This is an attached property.
        /// Grid defines RowSpan, so that it can be set
        /// on any element treated as a cell. RowSpan property
        /// specifies child's height with respect to row grid lines. 
        /// Example, RowSpan == 3 means that child will span across three rows.
        ///  
        ///  
        /// Default value for the property is 1.
        ///  
        [CommonDependencyProperty]
        public static readonly DependencyProperty RowSpanProperty =
                DependencyProperty.RegisterAttached(
                      "RowSpan", 
                      typeof(int),
                      typeof(Grid), 
                      new FrameworkPropertyMetadata( 
                              1,
                              new PropertyChangedCallback(OnCellAttachedPropertyChanged)), 
                      new ValidateValueCallback(IsIntValueGreaterThanZero));


        ///  
        /// IsSharedSizeScope property marks scoping element for shared size.
        ///  
        public static readonly DependencyProperty IsSharedSizeScopeProperty  = 
                DependencyProperty.RegisterAttached(
                      "IsSharedSizeScope", 
                      typeof(bool),
                      typeof(Grid),
                      new FrameworkPropertyMetadata(
                              false, 
                              new PropertyChangedCallback(DefinitionBase.OnIsSharedSizeScopePropertyChanged)));
 
        #endregion Properties 

        //----------------------------------------------------- 
        //
        //  Internal Structures / Classes
        //
        //------------------------------------------------------ 

        #region Internal Structures Classes 
 
        /// 
        /// LayoutTimeSizeType is used internally and reflects layout-time size type. 
        /// 
        [System.Flags]
        internal enum LayoutTimeSizeType : byte
        { 
            None        = 0x00,
            Pixel       = 0x01, 
            Auto        = 0x02, 
            Star        = 0x04,
        } 

        #endregion Internal Structures Classes

        //----------------------------------------------------- 
        //
        //  Private Structures / Classes 
        // 
        //-----------------------------------------------------
 
        #region Private Structures Classes

        /// 
        /// CellCache stored calculated values of 
        /// 1. attached cell positioning properties;
        /// 2. size type; 
        /// 3. index of a next cell in the group; 
        /// 
        private struct CellCache 
        {
            internal int ColumnIndex;
            internal int RowIndex;
            internal int ColumnSpan; 
            internal int RowSpan;
            internal LayoutTimeSizeType SizeTypeU; 
            internal LayoutTimeSizeType SizeTypeV; 
            internal int Next;
            internal bool IsStarU { get { return ((SizeTypeU & LayoutTimeSizeType.Star) != 0); } } 
            internal bool IsAutoU { get { return ((SizeTypeU & LayoutTimeSizeType.Auto) != 0); } }
            internal bool IsStarV { get { return ((SizeTypeV & LayoutTimeSizeType.Star) != 0); } }
            internal bool IsAutoV { get { return ((SizeTypeV & LayoutTimeSizeType.Auto) != 0); } }
        } 

        ///  
        /// Helper class for representing a key for a span in hashtable. 
        /// 
        private class SpanKey 
        {
            /// 
            /// Constructor.
            ///  
            /// Starting index of the span.
            /// Span count. 
            /// true for columns; false for rows. 
            internal SpanKey(int start, int count, bool u)
            { 
                _start = start;
                _count = count;
                _u = u;
            } 

            ///  
            ///  
            /// 
            public override int GetHashCode() 
            {
                int hash = (_start ^ (_count << 2));

                if (_u) hash &= 0x7ffffff; 
                else    hash |= 0x8000000;
 
                return (hash); 
            }
 
            /// 
            /// 
            /// 
            public override bool Equals(object obj) 
            {
                SpanKey sk = obj as SpanKey; 
                return (    sk != null 
                        &&  sk._start == _start
                        &&  sk._count == _count 
                        &&  sk._u == _u );
            }

            ///  
            /// Returns start index of the span.
            ///  
            internal int Start { get { return (_start); } } 

            ///  
            /// Returns span count.
            /// 
            internal int Count { get { return (_count); } }
 
            /// 
            /// Returns true if this is a column span. 
            /// false if this is a row span. 
            /// 
            internal bool U { get { return (_u); } } 

            private int _start;
            private int _count;
            private bool _u; 
        }
 
        ///  
        /// SpanPreferredDistributionOrderComparer.
        ///  
        private class SpanPreferredDistributionOrderComparer : IComparer
        {
            public int Compare(object x, object y)
            { 
                DefinitionBase definitionX = x as DefinitionBase;
                DefinitionBase definitionY = y as DefinitionBase; 
 
                int result;
 
                if (!CompareNullRefs(definitionX, definitionY, out result))
                {
                    if (definitionX.UserSize.IsAuto)
                    { 
                        if (definitionY.UserSize.IsAuto)
                        { 
                            result = definitionX.MinSize.CompareTo(definitionY.MinSize); 
                        }
                        else 
                        {
                            result = -1;
                        }
                    } 
                    else
                    { 
                        if (definitionY.UserSize.IsAuto) 
                        {
                            result = +1; 
                        }
                        else
                        {
                            result = definitionX.PreferredSize.CompareTo(definitionY.PreferredSize); 
                        }
                    } 
                } 

                return result; 
            }
        }

        ///  
        /// SpanMaxDistributionOrderComparer.
        ///  
        private class SpanMaxDistributionOrderComparer : IComparer 
        {
            public int Compare(object x, object y) 
            {
                DefinitionBase definitionX = x as DefinitionBase;
                DefinitionBase definitionY = y as DefinitionBase;
 
                int result;
 
                if (!CompareNullRefs(definitionX, definitionY, out result)) 
                {
                    if (definitionX.UserSize.IsAuto) 
                    {
                        if (definitionY.UserSize.IsAuto)
                        {
                            result = definitionX.SizeCache.CompareTo(definitionY.SizeCache); 
                        }
                        else 
                        { 
                            result = +1;
                        } 
                    }
                    else
                    {
                        if (definitionY.UserSize.IsAuto) 
                        {
                            result = -1; 
                        } 
                        else
                        { 
                            result = definitionX.SizeCache.CompareTo(definitionY.SizeCache);
                        }
                    }
                } 

                return result; 
            } 
        }
 
        /// 
        /// StarDistributionOrderComparer.
        /// 
        private class StarDistributionOrderComparer : IComparer 
        {
            public int Compare(object x, object y) 
            { 
                DefinitionBase definitionX = x as DefinitionBase;
                DefinitionBase definitionY = y as DefinitionBase; 

                int result;

                if (!CompareNullRefs(definitionX, definitionY, out result)) 
                {
                    result = definitionX.SizeCache.CompareTo(definitionY.SizeCache); 
                } 

                return result; 
            }
        }

        ///  
        /// DistributionOrderComparer.
        ///  
        private class DistributionOrderComparer: IComparer 
        {
            public int Compare(object x, object y) 
            {
                DefinitionBase definitionX = x as DefinitionBase;
                DefinitionBase definitionY = y as DefinitionBase;
 
                int result;
 
                if (!CompareNullRefs(definitionX, definitionY, out result)) 
                {
                    double xprime = definitionX.SizeCache - definitionX.MinSizeForArrange; 
                    double yprime = definitionY.SizeCache - definitionY.MinSizeForArrange;
                    result = xprime.CompareTo(yprime);
                }
 
                return result;
            } 
        } 

 
        /// 
        /// StarDistributionOrderIndexComparer.
        /// 
        private class StarDistributionOrderIndexComparer : IComparer 
        {
            private readonly DefinitionBase[] definitions; 
 
            internal StarDistributionOrderIndexComparer(DefinitionBase[] definitions)
            { 
                Invariant.Assert(definitions != null);
                this.definitions = definitions;
            }
 
            public int Compare(object x, object y)
            { 
                int? indexX = x as int?; 
                int? indexY = y as int?;
 
                DefinitionBase definitionX = null;
                DefinitionBase definitionY = null;

                if (indexX != null) 
                {
                    definitionX = definitions[indexX.Value]; 
                } 
                if (indexY != null)
                { 
                    definitionY = definitions[indexY.Value];
                }

                int result; 

                if (!CompareNullRefs(definitionX, definitionY, out result)) 
                { 
                    result = definitionX.SizeCache.CompareTo(definitionY.SizeCache);
                } 

                return result;
            }
        } 

        ///  
        /// DistributionOrderComparer. 
        /// 
        private class DistributionOrderIndexComparer : IComparer 
        {
            private readonly DefinitionBase[] definitions;

            internal DistributionOrderIndexComparer(DefinitionBase[] definitions) 
            {
                Invariant.Assert(definitions != null); 
                this.definitions = definitions; 
            }
 
            public int Compare(object x, object y)
            {
                int? indexX = x as int?;
                int? indexY = y as int?; 

                DefinitionBase definitionX = null; 
                DefinitionBase definitionY = null; 

                if (indexX != null) 
                {
                    definitionX = definitions[indexX.Value];
                }
                if (indexY != null) 
                {
                    definitionY = definitions[indexY.Value]; 
                } 

                int result; 

                if (!CompareNullRefs(definitionX, definitionY, out result))
                {
                    double xprime = definitionX.SizeCache - definitionX.MinSizeForArrange; 
                    double yprime = definitionY.SizeCache - definitionY.MinSizeForArrange;
                    result = xprime.CompareTo(yprime); 
                } 

                return result; 
            }
        }

        ///  
        /// RoundingErrorIndexComparer.
        ///  
        private class RoundingErrorIndexComparer : IComparer 
        {
            private readonly double[] errors; 

            internal RoundingErrorIndexComparer(double[] errors)
            {
                Invariant.Assert(errors != null); 
                this.errors = errors;
            } 
 
            public int Compare(object x, object y)
            { 
                int? indexX = x as int?;
                int? indexY = y as int?;

                int result; 

                if (!CompareNullRefs(indexX, indexY, out result)) 
                { 
                    double errorX = errors[indexX.Value];
                    double errorY = errors[indexY.Value]; 
                    result = errorX.CompareTo(errorY);
                }

                return result; 
            }
        } 
 
        /// 
        /// Implementation of a simple enumerator of grid's logical children 
        /// 
        private class GridChildrenCollectionEnumeratorSimple : IEnumerator
        {
            internal GridChildrenCollectionEnumeratorSimple(Grid grid, bool includeChildren) 
            {
                Debug.Assert(grid != null); 
                _currentEnumerator = -1; 
                _enumerator0 = new ColumnDefinitionCollection.Enumerator(grid.ExtData != null ? grid.ExtData.ColumnDefinitions : null);
                _enumerator1 = new RowDefinitionCollection.Enumerator(grid.ExtData != null ? grid.ExtData.RowDefinitions : null); 
                // GridLineRenderer is NOT included into this enumerator.
                _enumerator2Index = 0;
                if (includeChildren)
                { 
                    _enumerator2Collection = grid.Children;
                    _enumerator2Count = _enumerator2Collection.Count; 
                } 
                else
                { 
                    _enumerator2Collection = null;
                    _enumerator2Count = 0;
                }
            } 

            public bool MoveNext() 
            { 
                while (_currentEnumerator < 3)
                { 
                    if (_currentEnumerator >= 0)
                    {
                        switch (_currentEnumerator)
                        { 
                            case (0): if (_enumerator0.MoveNext()) { _currentChild = _enumerator0.Current; return (true); } break;
                            case (1): if (_enumerator1.MoveNext()) { _currentChild = _enumerator1.Current; return (true); } break; 
                            case (2): if (_enumerator2Index < _enumerator2Count) 
                                      {
                                          _currentChild = _enumerator2Collection[_enumerator2Index]; 
                                          _enumerator2Index++;
                                          return (true);
                                      }
                                      break; 
                        }
                    } 
                    _currentEnumerator++; 
                }
                return (false); 
            }

            public Object Current
            { 
                get
                { 
                    if (_currentEnumerator == -1) 
                    {
                        #pragma warning suppress 6503 // IEnumerator.Current is documented to throw this exception 
                        throw new InvalidOperationException(SR.Get(SRID.EnumeratorNotStarted));
                    }
                    if (_currentEnumerator >= 3)
                    { 
                        #pragma warning suppress 6503 // IEnumerator.Current is documented to throw this exception
                        throw new InvalidOperationException(SR.Get(SRID.EnumeratorReachedEnd)); 
                    } 

                    //  assert below is not true anymore since UIElementCollection allowes for null children 
                    //Debug.Assert(_currentChild != null);
                    return (_currentChild);
                }
            } 

            public void Reset() 
            { 
                _currentEnumerator = -1;
                _currentChild = null; 
                _enumerator0.Reset();
                _enumerator1.Reset();
                _enumerator2Index = 0;
            } 

            private int _currentEnumerator; 
            private Object _currentChild; 
            private ColumnDefinitionCollection.Enumerator _enumerator0;
            private RowDefinitionCollection.Enumerator _enumerator1; 
            private UIElementCollection _enumerator2Collection;
            private int _enumerator2Index;
            private int _enumerator2Count;
        } 

        ///  
        /// Helper to render grid lines. 
        /// 
        internal class GridLinesRenderer : DrawingVisual 
        {
            /// 
            /// Static initialization
            ///  
            static GridLinesRenderer()
            { 
                s_oddDashPen = new Pen(Brushes.Blue, c_penWidth); 
                DoubleCollection oddDashArray = new DoubleCollection();
                oddDashArray.Add(c_dashLength); 
                oddDashArray.Add(c_dashLength);
                s_oddDashPen.DashStyle = new DashStyle(oddDashArray, 0);
                s_oddDashPen.DashCap = PenLineCap.Flat;
                s_oddDashPen.Freeze(); 

                s_evenDashPen = new Pen(Brushes.Yellow, c_penWidth); 
                DoubleCollection evenDashArray = new DoubleCollection(); 
                evenDashArray.Add(c_dashLength);
                evenDashArray.Add(c_dashLength); 
                s_evenDashPen.DashStyle = new DashStyle(evenDashArray, c_dashLength);
                s_evenDashPen.DashCap = PenLineCap.Flat;
                s_evenDashPen.Freeze();
            } 

            ///  
            /// UpdateRenderBounds. 
            /// 
            /// Size of render bounds 
            internal void UpdateRenderBounds(Size boundsSize)
            {
                using (DrawingContext drawingContext = RenderOpen())
                { 
                    Grid grid = VisualTreeHelper.GetParent(this) as Grid;
                    if (    grid == null 
                        ||  grid.ShowGridLines == false ) 
                    {
                        return; 
                    }

                    for (int i = 1; i < grid.DefinitionsU.Length; ++i)
                    { 
                        DrawGridLine(
                            drawingContext, 
                            grid.DefinitionsU[i].FinalOffset, 0.0, 
                            grid.DefinitionsU[i].FinalOffset, boundsSize.Height);
                    } 

                    for (int i = 1; i < grid.DefinitionsV.Length; ++i)
                    {
                        DrawGridLine( 
                            drawingContext,
                            0.0, grid.DefinitionsV[i].FinalOffset, 
                            boundsSize.Width, grid.DefinitionsV[i].FinalOffset); 
                    }
                } 
            }

            /// 
            /// Draw single hi-contrast line. 
            /// 
            private static void DrawGridLine( 
                DrawingContext drawingContext, 
                double startX,
                double startY, 
                double endX,
                double endY)
            {
                Point start = new Point(startX, startY); 
                Point end = new Point(endX, endY);
                drawingContext.DrawLine(s_oddDashPen, start, end); 
                drawingContext.DrawLine(s_evenDashPen, start, end); 
            }
 
            private const double c_dashLength = 4.0;    //
            private const double c_penWidth = 1.0;      //
            private static readonly Pen s_oddDashPen;   //  first pen to draw dash
            private static readonly Pen s_evenDashPen;  //  second pen to draw dash 
            private static readonly Point c_zeroPoint = new Point(0, 0);
        } 
 
        #endregion Private Structures Classes
 
        //-----------------------------------------------------
        //
        //  Extended debugging for grid
        // 
        //------------------------------------------------------
 
#if GRIDPARANOIA 
        private static double _performanceFrequency;
        private static readonly bool _performanceFrequencyInitialized = InitializePerformanceFrequency(); 

        //CASRemoval:[System.Security.SuppressUnmanagedCodeSecurity, System.Runtime.InteropServices.DllImport("kernel32.dll")]
        private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
 
        //CASRemoval:[System.Security.SuppressUnmanagedCodeSecurity, System.Runtime.InteropServices.DllImport("kernel32.dll")]
        private static extern bool QueryPerformanceFrequency(out long lpFrequency); 
 
        private static double CostInMilliseconds(long count)
        { 
            return ((double)count / _performanceFrequency);
        }

        private static long Cost(long startCount, long endCount) 
        {
            long l = endCount - startCount; 
            if (l < 0)  { l += long.MaxValue;   } 
            return (l);
        } 

        private static bool InitializePerformanceFrequency()
        {
            long l; 
            QueryPerformanceFrequency(out l);
            _performanceFrequency = (double)l * 0.001; 
            return (true); 
        }
 
        private struct Counter
        {
            internal long   Start;
            internal long   Total; 
            internal int    Calls;
        } 
 
        private Counter[] _counters;
        private bool _hasNewCounterInfo; 
#endif // GRIDPARANOIA

        //
        //  This property 
        //  1. Finds the correct initial size for the _effectiveValues store on the current DependencyObject
        //  2. This is a performance optimization 
        // 
        internal override int EffectiveValuesInitialSize
        { 
            get { return 9; }
        }

        [Conditional("GRIDPARANOIA")] 
        internal void EnterCounterScope(Counters scopeCounter)
        { 
            #if GRIDPARANOIA 
            if (ID == "CountThis")
            { 
                if (_counters == null)
                {
                    _counters = new Counter[(int)Counters.Count];
                } 
                ExitCounterScope(Counters.Default);
                EnterCounter(scopeCounter); 
            } 
            else
            { 
                _counters = null;
            }
            #endif // GRIDPARANOIA
        } 

        [Conditional("GRIDPARANOIA")] 
        internal void ExitCounterScope(Counters scopeCounter) 
        {
            #if GRIDPARANOIA 
            if (_counters != null)
            {
                if (scopeCounter != Counters.Default)
                { 
                    ExitCounter(scopeCounter);
                } 
 
                if (_hasNewCounterInfo)
                { 
                    string NFormat = "F6";
                    Console.WriteLine(
                                "\ncounter name          | total t (ms)  | # of calls    | per call t (ms)"
                            +   "\n----------------------+---------------+---------------+----------------------" ); 

                    for (int i = 0; i < _counters.Length; ++i) 
                    { 
                        if (_counters[i].Calls > 0)
                        { 
                            Counters counter = (Counters)i;
                            double total = CostInMilliseconds(_counters[i].Total);
                            double single = total / _counters[i].Calls;
                            string counterName = counter.ToString(); 
                            string separator;
 
                            if (counterName.Length < 8)         { separator = "\t\t\t";  } 
                            else if (counterName.Length < 16)   { separator = "\t\t";    }
                            else                                { separator = "\t";      } 

                            Console.WriteLine(
                                    counter.ToString() + separator
                                +   total.ToString(NFormat) + "\t" 
                                +   _counters[i].Calls + "\t\t"
                                +   single.ToString(NFormat)); 
 
                            _counters[i] = new Counter();
                        } 
                    }
                }
                _hasNewCounterInfo = false;
            } 
            #endif // GRIDPARANOIA
        } 
 
        [Conditional("GRIDPARANOIA")]
        internal void EnterCounter(Counters counter) 
        {
            #if GRIDPARANOIA
            if (_counters != null)
            { 
                Debug.Assert((int)counter < _counters.Length);
 
                int i = (int)counter; 
                QueryPerformanceCounter(out _counters[i].Start);
            } 
            #endif // GRIDPARANOIA
        }

        [Conditional("GRIDPARANOIA")] 
        internal void ExitCounter(Counters counter)
        { 
            #if GRIDPARANOIA 
            if (_counters != null)
            { 
                Debug.Assert((int)counter < _counters.Length);

                int i = (int)counter;
                long l; 
                QueryPerformanceCounter(out l);
                l = Cost(_counters[i].Start, l); 
                _counters[i].Total += l; 
                _counters[i].Calls++;
                _hasNewCounterInfo = true; 
            }
            #endif // GRIDPARANOIA
        }
 
        internal enum Counters : int
        { 
            Default = -1, 

            MeasureOverride, 
            _ValidateColsStructure,
            _ValidateRowsStructure,
            _ValidateCells,
            _MeasureCell, 
            __MeasureChild,
            _CalculateDesiredSize, 
 
            ArrangeOverride,
            _SetFinalSize, 
            _ArrangeChildHelper2,
            _PositionCell,

            Count, 
        }
    } 
} 

 



// 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.
//  
//
// 
// Description: Grid implementation. 
//
// 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
// 
// History: 
//  09/24/2003 : olego - Created (in griddy prototype branch);
//  10/27/2003 : olego - Ported from griddy prototype branch; 
//  01/20/2004 : olego - Switching to use UIElementCollection;
//
//
 

 
 

 



 

 
 

 



 
using MS.Internal;
using MS.Internal.Controls; 
using MS.Internal.PresentationFramework; 
using MS.Utility;
 
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel; 
using System.Diagnostics;
using System.Windows.Threading; 
using System.Threading; 
using System.Windows;
using System.Windows.Controls; 
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows.Markup;
 
#pragma warning disable 1634, 1691  // suppressing PreSharp warnings
 
namespace System.Windows.Controls 
{
 
    /// 
    /// Grid
    /// 
    public class Grid : Panel, IAddChild 
    {
 
        //----------------------------------------------------- 
        //
        //  Constructors 
        //
        //-----------------------------------------------------

        #region Constructors 

        ///  
        /// Default constructor. 
        /// 
        public Grid() 
        {
            SetFlags((bool) ShowGridLinesProperty.GetDefaultValue(DependencyObjectType), Flags.ShowGridLinesPropertyValue);
        }
 
        #endregion Constructors
 
        //------------------------------------------------------ 
        //
        //  Public Methods 
        //
        //-----------------------------------------------------

        #region Public Methods 

        ///  
        ///  
        /// 
        void IAddChild.AddChild(object value) 
        {
            if (value == null)
            {
                throw new ArgumentNullException("value"); 
            }
 
            UIElement cell = value as UIElement; 
            if (cell != null)
            { 
                Children.Add(cell);
                return;
            }
 
            throw (new ArgumentException(SR.Get(SRID.Grid_UnexpectedParameterType, value.GetType(), typeof(UIElement)), "value"));
        } 
 
        /// 
        ///  
        /// 
        void IAddChild.AddText(string text)
        {
            XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this); 
        }
 
        ///  
        /// 
        ///  
        protected internal override IEnumerator LogicalChildren
        {
            get
            { 
                // empty panel or a panel being used as the items
                // host has *no* logical children; give empty enumerator 
                bool noChildren = (base.VisualChildrenCount == 0) || IsItemsHost; 

                if (noChildren) 
                {
                    ExtendedData extData = ExtData;

                    if (    extData == null 
                        ||  (   (extData.ColumnDefinitions == null || extData.ColumnDefinitions.Count == 0)
                            &&  (extData.RowDefinitions    == null || extData.RowDefinitions.Count    == 0) ) 
                       ) 
                    {
                        //  grid is empty 
                        return EmptyEnumerator.Instance;
                    }
                }
 
                return (new GridChildrenCollectionEnumeratorSimple(this, !noChildren));
            } 
        } 

        ///  
        /// Helper for setting Column property on a UIElement.
        /// 
        /// UIElement to set Column property on.
        /// Column property value. 
        public static void SetColumn(UIElement element, int value)
        { 
            if (element == null) 
            {
                throw new ArgumentNullException("element"); 
            }

            element.SetValue(ColumnProperty, value);
        } 

        ///  
        /// Helper for reading Column property from a UIElement. 
        /// 
        /// UIElement to read Column property from. 
        /// Column property value.
        [AttachedPropertyBrowsableForChildren()]
        public static int GetColumn(UIElement element)
        { 
            if (element == null)
            { 
                throw new ArgumentNullException("element"); 
            }
 
            return ((int)element.GetValue(ColumnProperty));
        }

        ///  
        /// Helper for setting Row property on a UIElement.
        ///  
        /// UIElement to set Row property on. 
        /// Row property value.
        public static void SetRow(UIElement element, int value) 
        {
            if (element == null)
            {
                throw new ArgumentNullException("element"); 
            }
 
            element.SetValue(RowProperty, value); 
        }
 
        /// 
        /// Helper for reading Row property from a UIElement.
        /// 
        /// UIElement to read Row property from. 
        /// Row property value.
        [AttachedPropertyBrowsableForChildren()] 
        public static int GetRow(UIElement element) 
        {
            if (element == null) 
            {
                throw new ArgumentNullException("element");
            }
 
            return ((int)element.GetValue(RowProperty));
        } 
 
        /// 
        /// Helper for setting ColumnSpan property on a UIElement. 
        /// 
        /// UIElement to set ColumnSpan property on.
        /// ColumnSpan property value.
        public static void SetColumnSpan(UIElement element, int value) 
        {
            if (element == null) 
            { 
                throw new ArgumentNullException("element");
            } 

            element.SetValue(ColumnSpanProperty, value);
        }
 
        /// 
        /// Helper for reading ColumnSpan property from a UIElement. 
        ///  
        /// UIElement to read ColumnSpan property from.
        /// ColumnSpan property value. 
        [AttachedPropertyBrowsableForChildren()]
        public static int GetColumnSpan(UIElement element)
        {
            if (element == null) 
            {
                throw new ArgumentNullException("element"); 
            } 

            return ((int)element.GetValue(ColumnSpanProperty)); 
        }

        /// 
        /// Helper for setting RowSpan property on a UIElement. 
        /// 
        /// UIElement to set RowSpan property on. 
        /// RowSpan property value. 
        public static void SetRowSpan(UIElement element, int value)
        { 
            if (element == null)
            {
                throw new ArgumentNullException("element");
            } 

            element.SetValue(RowSpanProperty, value); 
        } 

        ///  
        /// Helper for reading RowSpan property from a UIElement.
        /// 
        /// UIElement to read RowSpan property from.
        /// RowSpan property value. 
        [AttachedPropertyBrowsableForChildren()]
        public static int GetRowSpan(UIElement element) 
        { 
            if (element == null)
            { 
                throw new ArgumentNullException("element");
            }

            return ((int)element.GetValue(RowSpanProperty)); 
        }
 
        ///  
        /// Helper for setting IsSharedSizeScope property on a UIElement.
        ///  
        /// UIElement to set IsSharedSizeScope property on.
        /// IsSharedSizeScope property value.
        public static void SetIsSharedSizeScope(UIElement element, bool value)
        { 
            if (element == null)
            { 
                throw new ArgumentNullException("element"); 
            }
 
            element.SetValue(IsSharedSizeScopeProperty, value);
        }

        ///  
        /// Helper for reading IsSharedSizeScope property from a UIElement.
        ///  
        /// UIElement to read IsSharedSizeScope property from. 
        /// IsSharedSizeScope property value.
        public static bool GetIsSharedSizeScope(UIElement element) 
        {
            if (element == null)
            {
                throw new ArgumentNullException("element"); 
            }
 
            return ((bool)element.GetValue(IsSharedSizeScopeProperty)); 
        }
 
        #endregion Public Methods

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

        #region Public Properties 

        /// 
        /// ShowGridLines property.
        ///  
        public bool ShowGridLines
        { 
            get { return (CheckFlagsAnd(Flags.ShowGridLinesPropertyValue)); } 
            set { SetValue(ShowGridLinesProperty, value); }
        } 

        /// 
        /// Returns a ColumnDefinitionCollection of column definitions.
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public ColumnDefinitionCollection ColumnDefinitions 
        { 
            get
            { 
                if (_data == null) { _data = new ExtendedData(); }
                if (_data.ColumnDefinitions == null) { _data.ColumnDefinitions = new ColumnDefinitionCollection(this); }

                return (_data.ColumnDefinitions); 
            }
        } 
 
        /// 
        /// Returns a RowDefinitionCollection of row definitions. 
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public RowDefinitionCollection RowDefinitions
        { 
            get
            { 
                if (_data == null) { _data = new ExtendedData(); } 
                if (_data.RowDefinitions == null) { _data.RowDefinitions = new RowDefinitionCollection(this); }
 
                return (_data.RowDefinitions);
            }
        }
 
        #endregion Public Properties
 
        //----------------------------------------------------- 
        //
        //  Protected Methods 
        //
        //------------------------------------------------------

        #region Protected Methods 

        ///  
        ///   Derived class must implement to support Visual children. The method must return 
        ///    the child at the specified index. Index must be between 0 and GetVisualChildrenCount-1.
        /// 
        ///    By default a Visual does not have any children.
        ///
        ///  Remark:
        ///       During this virtual call it is not valid to modify the Visual tree. 
        /// 
        protected override Visual GetVisualChild(int index) 
        { 
            // because "base.Count + 1" for GridLinesRenderer
            // argument checking done at the base class 
            if(index == base.VisualChildrenCount)
            {
                if (_gridLinesRenderer == null)
                { 
                    throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange));
                } 
                return _gridLinesRenderer; 
            }
            else return base.GetVisualChild(index); 

        }

        ///  
        ///  Derived classes override this property to enable the Visual code to enumerate
        ///  the Visual children. Derived classes need to return the number of children 
        ///  from this method. 
        ///
        ///    By default a Visual does not have any children. 
        ///
        ///  Remark: During this virtual method the Visual tree must not be modified.
        /// 
        protected override int VisualChildrenCount 
        {
            //since GridLinesRenderer has not been added as a child, so we do not subtract 
            get { return base.VisualChildrenCount + (_gridLinesRenderer != null ? 1 : 0); } 
        }
 

        /// 
        /// Content measurement.
        ///  
        /// Constraint
        /// Desired size 
        protected override Size MeasureOverride(Size constraint) 
        {
            Size gridDesiredSize; 
            ExtendedData extData = ExtData;

            try
            { 
                EnterCounterScope(Counters.MeasureOverride);
 
                ListenToNotifications = true; 
                MeasureOverrideInProgress = true;
 
                if (extData == null)
                {
                    gridDesiredSize = new Size();
                    UIElementCollection children = InternalChildren; 

                    for (int i = 0, count = children.Count; i < count; ++i) 
                    { 
                        UIElement child = children[i];
                        if (child != null) 
                        {
                            Helper.SetMeasureDataOnChild(this, child, constraint);  // pass along MeasureData so it continues down the tree.
                            child.Measure(constraint);
                            gridDesiredSize.Width = Math.Max(gridDesiredSize.Width, child.DesiredSize.Width); 
                            gridDesiredSize.Height = Math.Max(gridDesiredSize.Height, child.DesiredSize.Height);
                        } 
                    } 
                }
                else 
                {
                    {
                        bool sizeToContentU = double.IsPositiveInfinity(constraint.Width);
                        bool sizeToContentV = double.IsPositiveInfinity(constraint.Height); 

                        // Clear index information and rounding errors 
                        if (RowDefinitionCollectionDirty || ColumnDefinitionCollectionDirty) 
                        {
                            if (_definitionIndices != null) 
                            {
                                Array.Clear(_definitionIndices, 0, _definitionIndices.Length);
                                _definitionIndices = null;
                            } 

                            if (UseLayoutRounding) 
                            { 
                                if (_roundingErrors != null)
                                { 
                                    Array.Clear(_roundingErrors, 0, _roundingErrors.Length);
                                    _roundingErrors = null;
                                }
                            } 
                        }
 
                        ValidateDefinitionsUStructure(); 
                        ValidateDefinitionsLayout(DefinitionsU, sizeToContentU);
 
                        ValidateDefinitionsVStructure();
                        ValidateDefinitionsLayout(DefinitionsV, sizeToContentV);

                        CellsStructureDirty |= (SizeToContentU != sizeToContentU) || (SizeToContentV != sizeToContentV); 

                        SizeToContentU = sizeToContentU; 
                        SizeToContentV = sizeToContentV; 
                    }
 
                    ValidateCells();

                    Debug.Assert(DefinitionsU.Length > 0 && DefinitionsV.Length > 0);
 
                    //  Grid classifies cells into four groups depending on
                    //  the column / row type a cell belongs to (number corresponds to 
                    //  group number): 
                    //
                    //                   Px      Auto     Star 
                    //               +--------+--------+--------+
                    //               |        |        |        |
                    //            Px |    1   |    1   |    3   |
                    //               |        |        |        | 
                    //               +--------+--------+--------+
                    //               |        |        |        | 
                    //          Auto |    1   |    1   |    3   | 
                    //               |        |        |        |
                    //               +--------+--------+--------+ 
                    //               |        |        |        |
                    //          Star |    4   |    2   |    4   |
                    //               |        |        |        |
                    //               +--------+--------+--------+ 
                    //
                    //  The group number indicates the order in which cells are measured. 
                    //  Certain order is necessary to be able to dynamically resolve star 
                    //  columns / rows sizes which are used as input for measuring of
                    //  the cells belonging to them. 
                    //
                    //  However, there are cases when topology of a grid causes cyclical
                    //  size dependences. For example:
                    // 
                    //
                    //                         column width="Auto"      column width="*" 
                    //                      +----------------------+----------------------+ 
                    //                      |                      |                      |
                    //                      |                      |                      | 
                    //                      |                      |                      |
                    //                      |                      |                      |
                    //  row height="Auto"   |                      |      cell 1 2        |
                    //                      |                      |                      | 
                    //                      |                      |                      |
                    //                      |                      |                      | 
                    //                      |                      |                      | 
                    //                      +----------------------+----------------------+
                    //                      |                      |                      | 
                    //                      |                      |                      |
                    //                      |                      |                      |
                    //                      |                      |                      |
                    //  row height="*"      |       cell 2 1       |                      | 
                    //                      |                      |                      |
                    //                      |                      |                      | 
                    //                      |                      |                      | 
                    //                      |                      |                      |
                    //                      +----------------------+----------------------+ 
                    //
                    //  In order to accurately calculate constraint width for "cell 1 2"
                    //  (which is the remaining of grid's available width and calculated
                    //  value of Auto column), "cell 2 1" needs to be calculated first, 
                    //  as it contributes to the Auto column's calculated value.
                    //  At the same time in order to accurately calculate constraint 
                    //  height for "cell 2 1", "cell 1 2" needs to be calcualted first, 
                    //  as it contributes to Auto row height, which is used in the
                    //  computation of Star row resolved height. 
                    //
                    //  to "break" this cyclical dependency we are making (arbitrary)
                    //  decision to treat cells like "cell 2 1" as if they appear in Auto
                    //  rows. And then recalculate them one more time when star row 
                    //  heights are resolved.
                    // 
                    //  (Or more strictly) the code below implement the following logic: 
                    //
                    //                       +---------+ 
                    //                       |  enter  |
                    //                       +---------+
                    //                            |
                    //                            V 
                    //                    +----------------+
                    //                    | Measure Group1 | 
                    //                    +----------------+ 
                    //                            |
                    //                            V 
                    //                          / - \
                    //                        /       \
                    //                  Y   /    Can    \    N
                    //            +--------|   Resolve   |-----------+ 
                    //            |         \  StarsV?  /            |
                    //            |           \       /              | 
                    //            |             \ - /                | 
                    //            V                                  V
                    //    +----------------+                       / - \ 
                    //    | Resolve StarsV |                     /       \
                    //    +----------------+               Y   /    Can    \    N
                    //            |                      +----|   Resolve   |------+
                    //            V                      |     \  StarsU?  /       | 
                    //    +----------------+             |       \       /         |
                    //    | Measure Group2 |             |         \ - /           | 
                    //    +----------------+             |                         V 
                    //            |                      |                 +-----------------+
                    //            V                      |                 | Measure Group2' | 
                    //    +----------------+             |                 +-----------------+
                    //    | Resolve StarsU |             |                         |
                    //    +----------------+             V                         V
                    //            |              +----------------+        +----------------+ 
                    //            V              | Resolve StarsU |        | Resolve StarsU |
                    //    +----------------+     +----------------+        +----------------+ 
                    //    | Measure Group3 |             |                         | 
                    //    +----------------+             V                         V
                    //            |              +----------------+        +----------------+ 
                    //            |              | Measure Group3 |        | Measure Group3 |
                    //            |              +----------------+        +----------------+
                    //            |                      |                         |
                    //            |                      V                         V 
                    //            |              +----------------+        +----------------+
                    //            |              | Resolve StarsV |        | Resolve StarsV | 
                    //            |              +----------------+        +----------------+ 
                    //            |                      |                         |
                    //            |                      |                         V 
                    //            |                      |                +------------------+
                    //            |                      |                | Measure Group2'' |
                    //            |                      |                +------------------+
                    //            |                      |                         | 
                    //            +----------------------+-------------------------+
                    //                                   | 
                    //                                   V 
                    //                           +----------------+
                    //                           | Measure Group4 | 
                    //                           +----------------+
                    //                                   |
                    //                                   V
                    //                               +--------+ 
                    //                               |  exit  |
                    //                               +--------+ 
                    // 
                    //  where:
                    //  *   all [Measure GroupN] - regular children measure process - 
                    //      each cell is measured given contraint size as an input
                    //      and each cell's desired size is accumulated on the
                    //      corresponding column / row;
                    //  *   [Measure Group2'] - is when each cell is measured with 
                    //      infinit height as a constraint and a cell's desired
                    //      height is ignored; 
                    //  *   [Measure Groups''] - is when each cell is measured (second 
                    //      time during single Grid.MeasureOverride) regularly but its
                    //      returned width is ignored; 
                    //
                    //  This algorithm is believed to be as close to ideal as possible.
                    //  It has the following drawbacks:
                    //  *   cells belonging to Group2 can be called to measure twice; 
                    //  *   iff during second measure a cell belonging to Group2 returns
                    //      desired width greater than desired width returned the first 
                    //      time, such a cell is going to be clipped, even though it 
                    //      appears in Auto column.
                    // 

                    MeasureCellsGroup(extData.CellGroup1, constraint, false, false);

                    { 
                        //  after Group1 is measured,  only Group3 may have cells belonging to Auto rows.
                        bool canResolveStarsV = !HasGroup3CellsInAutoRows; 
 
                        if (canResolveStarsV)
                        { 
                            if (HasStarCellsV) { ResolveStar(DefinitionsV, constraint.Height); }
                            MeasureCellsGroup(extData.CellGroup2, constraint, false, false);
                            if (HasStarCellsU) { ResolveStar(DefinitionsU, constraint.Width); }
                            MeasureCellsGroup(extData.CellGroup3, constraint, false, false); 
                        }
                        else 
                        { 
                            //  if at least one cell exists in Group2, it must be measured before
                            //  StarsU can be resolved. 
                            bool canResolveStarsU = extData.CellGroup2 > PrivateCells.Length;
                            if (canResolveStarsU)
                            {
                                if (HasStarCellsU) { ResolveStar(DefinitionsU, constraint.Width); } 
                                MeasureCellsGroup(extData.CellGroup3, constraint, false, false);
                                if (HasStarCellsV) { ResolveStar(DefinitionsV, constraint.Height); } 
                            } 
                            else
                            { 
                                MeasureCellsGroup(extData.CellGroup2, constraint, false, true);
                                if (HasStarCellsU) { ResolveStar(DefinitionsU, constraint.Width); }
                                MeasureCellsGroup(extData.CellGroup3, constraint, false, false);
                                if (HasStarCellsV) { ResolveStar(DefinitionsV, constraint.Height); } 
                                MeasureCellsGroup(extData.CellGroup2, constraint, true, false);
                            } 
                        } 
                    }
 
                    MeasureCellsGroup(extData.CellGroup4, constraint, false, false);

                    EnterCounter(Counters._CalculateDesiredSize);
                    gridDesiredSize = new Size( 
                            CalculateDesiredSize(DefinitionsU),
                            CalculateDesiredSize(DefinitionsV)); 
                    ExitCounter(Counters._CalculateDesiredSize); 
                }
            } 
            finally
            {
                MeasureOverrideInProgress = false;
                ExitCounterScope(Counters.MeasureOverride); 
            }
 
            return (gridDesiredSize); 
        }
 
        /// 
        /// Content arrangement.
        /// 
        /// Arrange size 
        protected override Size ArrangeOverride(Size arrangeSize)
        { 
            try 
            {
                EnterCounterScope(Counters.ArrangeOverride); 

                ArrangeOverrideInProgress = true;

                if (_data == null) 
                {
                    UIElementCollection children = InternalChildren; 
 
                    for (int i = 0, count = children.Count; i < count; ++i)
                    { 
                        UIElement child = children[i];
                        if (child != null)
                        {
                            child.Arrange(new Rect(arrangeSize)); 
                        }
                    } 
                } 
                else
                { 
                    Debug.Assert(DefinitionsU.Length > 0 && DefinitionsV.Length > 0);

                    EnterCounter(Counters._SetFinalSize);
 
                    SetFinalSize(DefinitionsU, arrangeSize.Width, true);
                    SetFinalSize(DefinitionsV, arrangeSize.Height, false); 
 
                    ExitCounter(Counters._SetFinalSize);
 
                    UIElementCollection children = InternalChildren;

                    for (int currentCell = 0; currentCell < PrivateCells.Length; ++currentCell)
                    { 
                        UIElement cell = children[currentCell];
                        if (cell == null) 
                        { 
                            continue;
                        } 

                        int columnIndex = PrivateCells[currentCell].ColumnIndex;
                        int rowIndex = PrivateCells[currentCell].RowIndex;
                        int columnSpan = PrivateCells[currentCell].ColumnSpan; 
                        int rowSpan = PrivateCells[currentCell].RowSpan;
 
                        Rect cellRect = new Rect( 
                            columnIndex == 0 ? 0.0 : DefinitionsU[columnIndex].FinalOffset,
                            rowIndex == 0 ? 0.0 : DefinitionsV[rowIndex].FinalOffset, 
                            GetFinalSizeForRange(DefinitionsU, columnIndex, columnSpan),
                            GetFinalSizeForRange(DefinitionsV, rowIndex, rowSpan)   );

                        EnterCounter(Counters._ArrangeChildHelper2); 
                        cell.Arrange(cellRect);
                        ExitCounter(Counters._ArrangeChildHelper2); 
                    } 

                    //  update render bound on grid lines renderer visual 
                    GridLinesRenderer gridLinesRenderer = EnsureGridLinesRenderer();
                    if (gridLinesRenderer != null)
                    {
                        gridLinesRenderer.UpdateRenderBounds(arrangeSize); 
                    }
                } 
            } 
            finally
            { 
                SetValid();
                ArrangeOverrideInProgress = false;
                ExitCounterScope(Counters.ArrangeOverride);
            } 
            return (arrangeSize);
        } 
 
        /// 
        ///  
        /// 
        protected internal override void OnVisualChildrenChanged(
            DependencyObject visualAdded,
            DependencyObject visualRemoved) 
        {
            CellsStructureDirty = true; 
 
            base.OnVisualChildrenChanged(visualAdded, visualRemoved);
        } 

        #endregion Protected Methods

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

        /// 
        ///     Invalidates grid caches and makes the grid dirty for measure. 
        /// 
        internal void Invalidate() 
        { 
            CellsStructureDirty = true;
            InvalidateMeasure(); 
        }

        /// 
        ///     Returns final width for a column. 
        /// 
        ///  
        ///     Used from public ColumnDefinition ActualWidth. Calculates final width using offset data. 
        /// 
        internal double GetFinalColumnDefinitionWidth(int columnIndex) 
        {
            double value = 0.0;

            Invariant.Assert(_data != null); 

            //  actual value calculations require structure to be up-to-date 
            if (!ColumnDefinitionCollectionDirty) 
            {
                DefinitionBase[] definitions = DefinitionsU; 
                value = definitions[(columnIndex + 1) % definitions.Length].FinalOffset;
                if (columnIndex != 0) { value -= definitions[columnIndex].FinalOffset; }
            }
            return (value); 
        }
 
        ///  
        ///     Returns final height for a row.
        ///  
        /// 
        ///     Used from public RowDefinition ActualHeight. Calculates final height using offset data.
        /// 
        internal double GetFinalRowDefinitionHeight(int rowIndex) 
        {
            double value = 0.0; 
 
            Invariant.Assert(_data != null);
 
            //  actual value calculations require structure to be up-to-date
            if (!RowDefinitionCollectionDirty)
            {
                DefinitionBase[] definitions = DefinitionsV; 
                value = definitions[(rowIndex + 1) % definitions.Length].FinalOffset;
                if (rowIndex != 0) { value -= definitions[rowIndex].FinalOffset; } 
            } 
            return (value);
        } 

        #endregion Internal Methods

        //----------------------------------------------------- 
        //
        //  Internal Properties 
        // 
        //------------------------------------------------------
 
        #region Internal Properties

        /// 
        /// Convenience accessor to MeasureOverrideInProgress bit flag. 
        /// 
        internal bool MeasureOverrideInProgress 
        { 
            get { return (CheckFlagsAnd(Flags.MeasureOverrideInProgress)); }
            set { SetFlags(value, Flags.MeasureOverrideInProgress); } 
        }

        /// 
        /// Convenience accessor to ArrangeOverrideInProgress bit flag. 
        /// 
        internal bool ArrangeOverrideInProgress 
        { 
            get { return (CheckFlagsAnd(Flags.ArrangeOverrideInProgress)); }
            set { SetFlags(value, Flags.ArrangeOverrideInProgress); } 
        }

        /// 
        /// Convenience accessor to ValidDefinitionsUStructure bit flag. 
        /// 
        internal bool ColumnDefinitionCollectionDirty 
        { 
            get { return (!CheckFlagsAnd(Flags.ValidDefinitionsUStructure)); }
            set { SetFlags(!value, Flags.ValidDefinitionsUStructure); } 
        }

        /// 
        /// Convenience accessor to ValidDefinitionsVStructure bit flag. 
        /// 
        internal bool RowDefinitionCollectionDirty 
        { 
            get { return (!CheckFlagsAnd(Flags.ValidDefinitionsVStructure)); }
            set { SetFlags(!value, Flags.ValidDefinitionsVStructure); } 
        }

        #endregion Internal Properties
 
        //-----------------------------------------------------
        // 
        //  Private Methods 
        //
        //------------------------------------------------------ 

        #region Private Methods

        ///  
        /// Lays out cells according to rows and columns, and creates lookup grids.
        ///  
        private void ValidateCells() 
        {
            EnterCounter(Counters._ValidateCells); 

            if (CellsStructureDirty)
            {
                ValidateCellsCore(); 
                CellsStructureDirty = false;
            } 
 
            ExitCounter(Counters._ValidateCells);
        } 

        /// 
        /// ValidateCellsCore
        ///  
        private void ValidateCellsCore()
        { 
            UIElementCollection children = InternalChildren; 
            ExtendedData extData = ExtData;
 
            extData.CellCachesCollection = new CellCache[children.Count];
            extData.CellGroup1 = int.MaxValue;
            extData.CellGroup2 = int.MaxValue;
            extData.CellGroup3 = int.MaxValue; 
            extData.CellGroup4 = int.MaxValue;
 
            bool hasStarCellsU = false; 
            bool hasStarCellsV = false;
            bool hasGroup3CellsInAutoRows = false; 

            for (int i = PrivateCells.Length - 1; i >= 0; --i)
            {
                UIElement child = children[i]; 
                if (child == null)
                { 
                    continue; 
                }
 
                CellCache cell = new CellCache();

                //
                //  read and cache child positioning properties 
                //
 
                //  read indices from the corresponding properties 
                //      clamp to value < number_of_columns
                //      column >= 0 is guaranteed by property value validation callback 
                cell.ColumnIndex = Math.Min(GetColumn(child), DefinitionsU.Length - 1);
                //      clamp to value < number_of_rows
                //      row >= 0 is guaranteed by property value validation callback
                cell.RowIndex = Math.Min(GetRow(child), DefinitionsV.Length - 1); 

                //  read span properties 
                //      clamp to not exceed beyond right side of the grid 
                //      column_span > 0 is guaranteed by property value validation callback
                cell.ColumnSpan = Math.Min(GetColumnSpan(child), DefinitionsU.Length - cell.ColumnIndex); 

                //      clamp to not exceed beyond bottom side of the grid
                //      row_span > 0 is guaranteed by property value validation callback
                cell.RowSpan = Math.Min(GetRowSpan(child), DefinitionsV.Length - cell.RowIndex); 

                Debug.Assert(0 <= cell.ColumnIndex && cell.ColumnIndex < DefinitionsU.Length); 
                Debug.Assert(0 <= cell.RowIndex && cell.RowIndex < DefinitionsV.Length); 

                // 
                //  calculate and cache length types for the child
                //

                cell.SizeTypeU = GetLengthTypeForRange(DefinitionsU, cell.ColumnIndex, cell.ColumnSpan); 
                cell.SizeTypeV = GetLengthTypeForRange(DefinitionsV, cell.RowIndex, cell.RowSpan);
 
                hasStarCellsU |= cell.IsStarU; 
                hasStarCellsV |= cell.IsStarV;
 
                //
                //  distribute cells into four groups.
                //
 
                if (!cell.IsStarV)
                { 
                    if (!cell.IsStarU) 
                    {
                        cell.Next = extData.CellGroup1; 
                        extData.CellGroup1 = i;
                    }
                    else
                    { 
                        cell.Next = extData.CellGroup3;
                        extData.CellGroup3 = i; 
 
                        //  remember if this cell belongs to auto row
                        hasGroup3CellsInAutoRows |= cell.IsAutoV; 
                    }
                }
                else
                { 
                    if (    cell.IsAutoU
                            //  note below: if spans through Star column it is NOT Auto 
                        &&  !cell.IsStarU ) 
                    {
                        cell.Next = extData.CellGroup2; 
                        extData.CellGroup2 = i;
                    }
                    else
                    { 
                        cell.Next = extData.CellGroup4;
                        extData.CellGroup4 = i; 
                    } 
                }
 
                PrivateCells[i] = cell;
            }

            HasStarCellsU = hasStarCellsU; 
            HasStarCellsV = hasStarCellsV;
            HasGroup3CellsInAutoRows = hasGroup3CellsInAutoRows; 
        } 

        ///  
        /// Initializes DefinitionsU memeber either to user supplied ColumnDefinitions collection
        /// or to a default single element collection. DefinitionsU gets trimmed to size.
        /// 
        ///  
        /// This is one of two methods, where ColumnDefinitions and DefinitionsU are directly accessed.
        /// All the rest measure / arrange / render code must use DefinitionsU. 
        ///  
        private void ValidateDefinitionsUStructure()
        { 
            EnterCounter(Counters._ValidateColsStructure);

            if (ColumnDefinitionCollectionDirty)
            { 
                ExtendedData extData = ExtData;
 
                if (extData.ColumnDefinitions == null) 
                {
                    if (extData.DefinitionsU == null) 
                    {
                        extData.DefinitionsU = new DefinitionBase[] { new ColumnDefinition() };
                    }
                } 
                else
                { 
                    extData.ColumnDefinitions.InternalTrimToSize(); 

                    if (extData.ColumnDefinitions.InternalCount == 0) 
                    {
                        //  if column definitions collection is empty
                        //  mockup array with one column
                        extData.DefinitionsU = new DefinitionBase[] { new ColumnDefinition() }; 
                    }
                    else 
                    { 
                        extData.DefinitionsU = extData.ColumnDefinitions.InternalItems;
                    } 
                }

                ColumnDefinitionCollectionDirty = false;
            } 

            Debug.Assert(ExtData.DefinitionsU != null && ExtData.DefinitionsU.Length > 0); 
 
            ExitCounter(Counters._ValidateColsStructure);
        } 

        /// 
        /// Initializes DefinitionsV memeber either to user supplied RowDefinitions collection
        /// or to a default single element collection. DefinitionsV gets trimmed to size. 
        /// 
        ///  
        /// This is one of two methods, where RowDefinitions and DefinitionsV are directly accessed. 
        /// All the rest measure / arrange / render code must use DefinitionsV.
        ///  
        private void ValidateDefinitionsVStructure()
        {
            EnterCounter(Counters._ValidateRowsStructure);
 
            if (RowDefinitionCollectionDirty)
            { 
                ExtendedData extData = ExtData; 

                if (extData.RowDefinitions == null) 
                {
                    if (extData.DefinitionsV == null)
                    {
                        extData.DefinitionsV = new DefinitionBase[] { new RowDefinition() }; 
                    }
                } 
                else 
                {
                    extData.RowDefinitions.InternalTrimToSize(); 

                    if (extData.RowDefinitions.InternalCount == 0)
                    {
                        //  if row definitions collection is empty 
                        //  mockup array with one row
                        extData.DefinitionsV = new DefinitionBase[] { new RowDefinition() }; 
                    } 
                    else
                    { 
                        extData.DefinitionsV = extData.RowDefinitions.InternalItems;
                    }
                }
 
                RowDefinitionCollectionDirty = false;
            } 
 
            Debug.Assert(ExtData.DefinitionsV != null && ExtData.DefinitionsV.Length > 0);
 
            ExitCounter(Counters._ValidateRowsStructure);
        }

        ///  
        /// Validates layout time size type information on given array of definitions.
        /// Sets MinSize and MeasureSizes. 
        ///  
        /// Array of definitions to update.
        /// if "true" then star definitions are treated as Auto. 
        private void ValidateDefinitionsLayout(
            DefinitionBase[] definitions,
            bool treatStarAsAuto)
        { 
            for (int i = 0; i < definitions.Length; ++i)
            { 
                definitions[i].OnBeforeLayout(this); 

                double userMinSize = definitions[i].UserMinSize; 
                double userMaxSize = definitions[i].UserMaxSize;
                double userSize = 0;

                switch (definitions[i].UserSize.GridUnitType) 
                {
                    case (GridUnitType.Pixel): 
                        definitions[i].SizeType = LayoutTimeSizeType.Pixel; 
                        userSize = definitions[i].UserSize.Value;
                        // this was brought with NewLayout and defeats squishy behavior 
                        userMinSize = Math.Max(userMinSize, Math.Min(userSize, userMaxSize));
                        break;
                    case (GridUnitType.Auto):
                        definitions[i].SizeType = LayoutTimeSizeType.Auto; 
                        userSize = double.PositiveInfinity;
                        break; 
                    case (GridUnitType.Star): 
                        if (treatStarAsAuto)
                        { 
                            definitions[i].SizeType = LayoutTimeSizeType.Auto;
                            userSize = double.PositiveInfinity;
                        }
                        else 
                        {
                            definitions[i].SizeType = LayoutTimeSizeType.Star; 
                            userSize = double.PositiveInfinity; 
                        }
                        break; 
                    default:
                        Debug.Assert(false);
                        break;
                } 

                definitions[i].UpdateMinSize(userMinSize); 
                definitions[i].MeasureSize = Math.Max(userMinSize, Math.Min(userSize, userMaxSize)); 
            }
        } 

        /// 
        /// Measures one group of cells.
        ///  
        /// Head index of the cells chain.
        /// Reference size for spanned cells 
        /// calculations. 
        /// When "true" cells' desired
        /// width is not registered in columns. 
        /// Passed through to MeasureCell.
        /// When "true" cells' desired height is not registered in rows.
        private void MeasureCellsGroup(
            int cellsHead, 
            Size referenceSize,
            bool ignoreDesiredSizeU, 
            bool forceInfinityV) 
        {
            if (cellsHead >= PrivateCells.Length) 
            {
                return;
            }
 
            UIElementCollection children = InternalChildren;
            Hashtable spanStore = null; 
            bool ignoreDesiredSizeV = forceInfinityV; 

            int i = cellsHead; 
            do
            {
                MeasureCell(i, forceInfinityV);
 
                if (!ignoreDesiredSizeU)
                { 
                    if (PrivateCells[i].ColumnSpan == 1) 
                    {
                        DefinitionsU[PrivateCells[i].ColumnIndex].UpdateMinSize(Math.Min(children[i].DesiredSize.Width, DefinitionsU[PrivateCells[i].ColumnIndex].UserMaxSize)); 
                    }
                    else
                    {
                        RegisterSpan( 
                            ref spanStore,
                            PrivateCells[i].ColumnIndex, 
                            PrivateCells[i].ColumnSpan, 
                            true,
                            children[i].DesiredSize.Width); 
                    }
                }

                if (!ignoreDesiredSizeV) 
                {
                    if (PrivateCells[i].RowSpan == 1) 
                    { 
                        DefinitionsV[PrivateCells[i].RowIndex].UpdateMinSize(Math.Min(children[i].DesiredSize.Height, DefinitionsV[PrivateCells[i].RowIndex].UserMaxSize));
                    } 
                    else
                    {
                        RegisterSpan(
                            ref spanStore, 
                            PrivateCells[i].RowIndex,
                            PrivateCells[i].RowSpan, 
                            false, 
                            children[i].DesiredSize.Height);
                    } 
                }

                i = PrivateCells[i].Next;
            } while (i < PrivateCells.Length); 

            if (spanStore != null) 
            { 
                foreach (DictionaryEntry e in spanStore)
                { 
                    SpanKey key = (SpanKey)e.Key;
                    double requestedSize = (double)e.Value;

                    EnsureMinSizeInDefinitionRange( 
                        key.U ? DefinitionsU : DefinitionsV,
                        key.Start, 
                        key.Count, 
                        requestedSize,
                        key.U ? referenceSize.Width : referenceSize.Height); 
                }
            }
        }
 
        /// 
        /// Helper method to register a span information for delayed processing. 
        ///  
        /// Reference to a hashtable object used as storage.
        /// Span starting index. 
        /// Span count.
        /// true if this is a column span. false if this is a row span.
        /// Value to store. If an entry already exists the biggest value is stored.
        private static void RegisterSpan( 
            ref Hashtable store,
            int start, 
            int count, 
            bool u,
            double value) 
        {
            if (store == null)
            {
                store = new Hashtable(); 
            }
 
            SpanKey key = new SpanKey(start, count, u); 
            object o = store[key];
 
            if (    o == null
                ||  value > (double)o   )
            {
                store[key] = value; 
            }
        } 
 
        /// 
        /// Takes care of measuring a single cell. 
        /// 
        /// Index of the cell to measure.
        /// If "true" then cell is always
        /// calculated to infinite height. 
        private void MeasureCell(
            int cell, 
            bool forceInfinityV) 
        {
            EnterCounter(Counters._MeasureCell); 

            double cellMeasureWidth;
            double cellMeasureHeight;
 
            if (    PrivateCells[cell].IsAutoU
                &&  !PrivateCells[cell].IsStarU   ) 
            { 
                //  if cell belongs to at least one Auto column and not a single Star column
                //  then it should be calculated "to content", thus it is possible to "shortcut" 
                //  calculations and simply assign PositiveInfinity here.
                cellMeasureWidth = double.PositiveInfinity;
            }
            else 
            {
                //  otherwise... 
                cellMeasureWidth = GetMeasureSizeForRange( 
                                        DefinitionsU,
                                        PrivateCells[cell].ColumnIndex, 
                                        PrivateCells[cell].ColumnSpan);
            }

            if (forceInfinityV) 
            {
                cellMeasureHeight = double.PositiveInfinity; 
            } 
            else if (   PrivateCells[cell].IsAutoV
                    &&  !PrivateCells[cell].IsStarV   ) 
            {
                //  if cell belongs to at least one Auto row and not a single Star row
                //  then it should be calculated "to content", thus it is possible to "shortcut"
                //  calculations and simply assign PositiveInfinity here. 
                cellMeasureHeight = double.PositiveInfinity;
            } 
            else 
            {
                cellMeasureHeight = GetMeasureSizeForRange( 
                                        DefinitionsV,
                                        PrivateCells[cell].RowIndex,
                                        PrivateCells[cell].RowSpan);
            } 

            EnterCounter(Counters.__MeasureChild); 
            UIElement child = InternalChildren[cell]; 
            if (child != null)
            { 
                Size childConstraint = new Size(cellMeasureWidth, cellMeasureHeight);
                Helper.SetMeasureDataOnChild(this, child, childConstraint);  // pass along MeasureData so it continues down the tree.
                child.Measure(childConstraint);
            } 
            ExitCounter(Counters.__MeasureChild);
 
            ExitCounter(Counters._MeasureCell); 
        }
 

        /// 
        /// Calculates one dimensional measure size for given definitions' range.
        ///  
        /// Source array of definitions to read values from.
        /// Starting index of the range. 
        /// Number of definitions included in the range. 
        /// Calculated measure size.
        ///  
        /// For "Auto" definitions MinWidth is used in place of PreferredSize.
        /// 
        private double GetMeasureSizeForRange(
            DefinitionBase[] definitions, 
            int start,
            int count) 
        { 
            Debug.Assert(0 < count && 0 <= start && (start + count) <= definitions.Length);
 
            double measureSize = 0;
            int i = start + count - 1;

            do 
            {
                measureSize += (definitions[i].SizeType == LayoutTimeSizeType.Auto) 
                    ? definitions[i].MinSize 
                    : definitions[i].MeasureSize;
            } while (--i >= start); 

            return (measureSize);
        }
 
        /// 
        /// Accumulates length type information for given definition's range. 
        ///  
        /// Source array of definitions to read values from.
        /// Starting index of the range. 
        /// Number of definitions included in the range.
        /// Length type for given range.
        private LayoutTimeSizeType GetLengthTypeForRange(
            DefinitionBase[] definitions, 
            int start,
            int count) 
        { 
            Debug.Assert(0 < count && 0 <= start && (start + count) <= definitions.Length);
 
            LayoutTimeSizeType lengthType = LayoutTimeSizeType.None;
            int i = start + count - 1;

            do 
            {
                lengthType |= definitions[i].SizeType; 
            } while (--i >= start); 

            return (lengthType); 
        }

        /// 
        /// Distributes min size back to definition array's range. 
        /// 
        /// Start of the range. 
        /// Number of items in the range. 
        /// Minimum size that should "fit" into the definitions range.
        /// Definition array receiving distribution. 
        /// Size used to resolve percentages.
        private void EnsureMinSizeInDefinitionRange(
            DefinitionBase[] definitions,
            int start, 
            int count,
            double requestedSize, 
            double percentReferenceSize) 
        {
            Debug.Assert(1 < count && 0 <= start && (start + count) <= definitions.Length); 

            //  avoid processing when asked to distribute "0"
            if (!_IsZero(requestedSize))
            { 
                DefinitionBase[] tempDefinitions = TempDefinitions; //  temp array used to remember definitions for sorting
                int end = start + count; 
                int autoDefinitionsCount = 0; 
                double rangeMinSize = 0;
                double rangePreferredSize = 0; 
                double rangeMaxSize = 0;
                double maxMaxSize = 0;                              //  maximum of maximum sizes

                //  first accumulate the necessary information: 
                //  a) sum up the sizes in the range;
                //  b) count the number of auto definitions in the range; 
                //  c) initialize temp array 
                //  d) cache the maximum size into SizeCache
                //  e) accumulate max of max sizes 
                for (int i = start; i < end; ++i)
                {
                    double minSize = definitions[i].MinSize;
                    double preferredSize = definitions[i].PreferredSize; 
                    double maxSize = Math.Max(definitions[i].UserMaxSize, minSize);
 
                    rangeMinSize += minSize; 
                    rangePreferredSize += preferredSize;
                    rangeMaxSize += maxSize; 

                    definitions[i].SizeCache = maxSize;

                    //  sanity check: no matter what, but min size must always be the smaller; 
                    //  max size must be the biggest; and preferred should be in between
                    Debug.Assert(   minSize <= preferredSize 
                                &&  preferredSize <= maxSize 
                                &&  rangeMinSize <= rangePreferredSize
                                &&  rangePreferredSize <= rangeMaxSize  ); 

                    if (maxMaxSize < maxSize)   maxMaxSize = maxSize;
                    if (definitions[i].UserSize.IsAuto) autoDefinitionsCount++;
                    tempDefinitions[i - start] = definitions[i]; 
                }
 
                //  avoid processing if the range already big enough 
                if (requestedSize > rangeMinSize)
                { 
                    if (requestedSize <= rangePreferredSize)
                    {
                        //
                        //  requestedSize fits into preferred size of the range. 
                        //  distribute according to the following logic:
                        //  * do not distribute into auto definitions - they should continue to stay "tight"; 
                        //  * for all non-auto definitions distribute to equi-size min sizes, without exceeding preferred size. 
                        //
                        //  in order to achieve that, definitions are sorted in a way that all auto definitions 
                        //  are first, then definitions follow ascending order with PreferredSize as the key of sorting.
                        //
                        double sizeToDistribute;
                        int i; 

                        Array.Sort(tempDefinitions, 0, count, s_spanPreferredDistributionOrderComparer); 
                        for (i = 0, sizeToDistribute = requestedSize; i < autoDefinitionsCount; ++i) 
                        {
                            //  sanity check: only auto definitions allowed in this loop 
                            Debug.Assert(tempDefinitions[i].UserSize.IsAuto);

                            //  adjust sizeToDistribute value by subtracting auto definition min size
                            sizeToDistribute -= (tempDefinitions[i].MinSize); 
                        }
 
                        for (; i < count; ++i) 
                        {
                            //  sanity check: no auto definitions allowed in this loop 
                            Debug.Assert(!tempDefinitions[i].UserSize.IsAuto);

                            double newMinSize = Math.Min(sizeToDistribute / (count - i), tempDefinitions[i].PreferredSize);
                            if (newMinSize > tempDefinitions[i].MinSize) { tempDefinitions[i].UpdateMinSize(newMinSize); } 
                            sizeToDistribute -= newMinSize;
                        } 
 
                        //  sanity check: requested size must all be distributed
                        Debug.Assert(_IsZero(sizeToDistribute)); 
                    }
                    else if (requestedSize <= rangeMaxSize)
                    {
                        // 
                        //  requestedSize bigger than preferred size, but fit into max size of the range.
                        //  distribute according to the following logic: 
                        //  * do not distribute into auto definitions, if possible - they should continue to stay "tight"; 
                        //  * for all non-auto definitions distribute to euqi-size min sizes, without exceeding max size.
                        // 
                        //  in order to achieve that, definitions are sorted in a way that all non-auto definitions
                        //  are last, then definitions follow ascending order with MaxSize as the key of sorting.
                        //
                        double sizeToDistribute; 
                        int i;
 
                        Array.Sort(tempDefinitions, 0, count, s_spanMaxDistributionOrderComparer); 
                        for (i = 0, sizeToDistribute = requestedSize - rangePreferredSize; i < count - autoDefinitionsCount; ++i)
                        { 
                            //  sanity check: no auto definitions allowed in this loop
                            Debug.Assert(!tempDefinitions[i].UserSize.IsAuto);

                            double preferredSize = tempDefinitions[i].PreferredSize; 
                            double newMinSize = preferredSize + sizeToDistribute / (count - autoDefinitionsCount - i);
                            tempDefinitions[i].UpdateMinSize(Math.Min(newMinSize, tempDefinitions[i].SizeCache)); 
                            sizeToDistribute -= (tempDefinitions[i].MinSize - preferredSize); 
                        }
 
                        for (; i < count; ++i)
                        {
                            //  sanity check: only auto definitions allowed in this loop
                            Debug.Assert(tempDefinitions[i].UserSize.IsAuto); 

                            double preferredSize = tempDefinitions[i].MinSize; 
                            double newMinSize = preferredSize + sizeToDistribute / (count - i); 
                            tempDefinitions[i].UpdateMinSize(Math.Min(newMinSize, tempDefinitions[i].SizeCache));
                            sizeToDistribute -= (tempDefinitions[i].MinSize - preferredSize); 
                        }

                        //  sanity check: requested size must all be distributed
                        Debug.Assert(_IsZero(sizeToDistribute)); 
                    }
                    else 
                    { 
                        //
                        //  requestedSize bigger than max size of the range. 
                        //  distribute according to the following logic:
                        //  * for all definitions distribute to equi-size min sizes.
                        //
                        double equalSize = requestedSize / count; 

                        if (    equalSize < maxMaxSize 
                            &&  !_AreClose(equalSize, maxMaxSize)   ) 
                        {
                            //  equi-size is less than maximum of maxSizes. 
                            //  in this case distribute so that smaller definitions grow faster than
                            //  bigger ones.
                            double totalRemainingSize = maxMaxSize * count - rangeMaxSize;
                            double sizeToDistribute = requestedSize - rangeMaxSize; 

                            //  sanity check: totalRemainingSize and sizeToDistribute must be real positive numbers 
                            Debug.Assert(   !double.IsInfinity(totalRemainingSize) 
                                        &&  !DoubleUtil.IsNaN(totalRemainingSize)
                                        &&  totalRemainingSize > 0 
                                        &&  !double.IsInfinity(sizeToDistribute)
                                        &&  !DoubleUtil.IsNaN(sizeToDistribute)
                                        &&  sizeToDistribute > 0    );
 
                            for (int i = 0; i < count; ++i)
                            { 
                                double deltaSize = (maxMaxSize - tempDefinitions[i].SizeCache) * sizeToDistribute / totalRemainingSize; 
                                tempDefinitions[i].UpdateMinSize(tempDefinitions[i].SizeCache + deltaSize);
                            } 
                        }
                        else
                        {
                            // 
                            //  equi-size is greater or equal to maximum of max sizes.
                            //  all definitions receive equalSize as their mim sizes. 
                            // 
                            for (int i = 0; i < count; ++i)
                            { 
                                tempDefinitions[i].UpdateMinSize(equalSize);
                            }
                        }
                    } 
                }
            } 
        } 

        ///  
        /// Resolves Star's for given array of definitions.
        /// 
        /// Array of definitions to resolve stars.
        /// All available size. 
        /// 
        /// Must initialize LayoutSize for all Star entries in given array of definitions. 
        ///  
        private void ResolveStar(
            DefinitionBase[] definitions, 
            double availableSize)
        {
            DefinitionBase[] tempDefinitions = TempDefinitions;
            int starDefinitionsCount = 0; 
            double takenSize = 0;
 
            for (int i = 0; i < definitions.Length; ++i) 
            {
                switch (definitions[i].SizeType) 
                {
                    case (LayoutTimeSizeType.Auto):
                        takenSize += definitions[i].MinSize;
                        break; 
                    case (LayoutTimeSizeType.Pixel):
                        takenSize += definitions[i].MeasureSize; 
                        break; 
                    case (LayoutTimeSizeType.Star):
                        { 
                            tempDefinitions[starDefinitionsCount++] = definitions[i];

                            double starValue = definitions[i].UserSize.Value;
 
                            if (_IsZero(starValue))
                            { 
                                definitions[i].MeasureSize = 0; 
                                definitions[i].SizeCache = 0;
                            } 
                            else
                            {
                                //  clipping by c_starClip guarantees that sum of even a very big number of max'ed out star values
                                //  can be summed up without overflow 
                                starValue = Math.Min(starValue, c_starClip);
 
                                //  Note: normalized star value is temporary cached into MeasureSize 
                                definitions[i].MeasureSize = starValue;
                                double maxSize             = Math.Max(definitions[i].MinSize, definitions[i].UserMaxSize); 
                                maxSize                    = Math.Min(maxSize, c_starClip);
                                definitions[i].SizeCache   = maxSize / starValue;
                            }
                        } 
                        break;
                } 
            } 

            if (starDefinitionsCount > 0) 
            {
                Array.Sort(tempDefinitions, 0, starDefinitionsCount, s_starDistributionOrderComparer);

                //  the 'do {} while' loop below calculates sum of star weights in order to avoid fp overflow... 
                //  partial sum value is stored in each definition's SizeCache member.
                //  this way the algorithm guarantees (starValue <= definition.SizeCache) and thus 
                //  (starValue / definition.SizeCache) will never overflow due to sum of star weights becoming zero. 
                //  this is an important change from previous implementation where the following was possible:
                //  ((BigValueStar + SmallValueStar) - BigValueStar) resulting in 0... 
                double allStarWeights = 0;
                int i = starDefinitionsCount - 1;
                do
                { 
                    allStarWeights += tempDefinitions[i].MeasureSize;
                    tempDefinitions[i].SizeCache = allStarWeights; 
                } while (--i >= 0); 

                i = 0; 
                do
                {
                    double resolvedSize;
                    double starValue = tempDefinitions[i].MeasureSize; 

                    if (_IsZero(starValue)) 
                    { 
                        resolvedSize = tempDefinitions[i].MinSize;
                    } 
                    else
                    {
                        double userSize = Math.Max(availableSize - takenSize, 0.0) * (starValue / tempDefinitions[i].SizeCache);
                        resolvedSize    = Math.Min(userSize, tempDefinitions[i].UserMaxSize); 
                        resolvedSize    = Math.Max(tempDefinitions[i].MinSize, resolvedSize);
                    } 
 
                    tempDefinitions[i].MeasureSize = resolvedSize;
                    takenSize                     += resolvedSize; 
                } while (++i < starDefinitionsCount);
            }
        }
 
        /// 
        /// Calculates desired size for given array of definitions. 
        ///  
        /// Array of definitions to use for calculations.
        /// Desired size. 
        private double CalculateDesiredSize(
            DefinitionBase[] definitions)
        {
            double desiredSize = 0; 

            for (int i = 0; i < definitions.Length; ++i) 
            { 
                desiredSize += definitions[i].MinSize;
            } 

            return (desiredSize);
        }
 
        /// 
        /// Calculates and sets final size for all definitions in the given array. 
        ///  
        /// Array of definitions to process.
        /// Final size to lay out to. 
        /// True if sizing row definitions, false for columns
        private void SetFinalSize(
            DefinitionBase[] definitions,
            double finalSize, 
            bool columns)
        { 
            int starDefinitionsCount = 0;                       //  traverses form the first entry up 
            int nonStarIndex = definitions.Length;              //  traverses from the last entry down
            double allPreferredArrangeSize = 0; 
            bool useLayoutRounding = this.UseLayoutRounding;
            int[] definitionIndices = DefinitionIndices;
            double[] roundingErrors = null;
 
            // If using layout rounding, check whether rounding needs to compensate for high DPI
            double dpi = 1.0; 
 
            if (useLayoutRounding)
            { 
                dpi = columns ? FrameworkElement.DpiScaleX : FrameworkElement.DpiScaleY;
                roundingErrors = RoundingErrors;
            }
 
            for (int i = 0; i < definitions.Length; ++i)
            { 
                //  if definition is shared then is cannot be star 
                Debug.Assert(!definitions[i].IsShared || !definitions[i].UserSize.IsStar);
 
                if (definitions[i].UserSize.IsStar)
                {
                    double starValue = definitions[i].UserSize.Value;
 
                    if (_IsZero(starValue))
                    { 
                        //  cach normilized star value temporary into MeasureSize 
                        definitions[i].MeasureSize = 0;
                        definitions[i].SizeCache = 0; 
                    }
                    else
                    {
                        //  clipping by c_starClip guarantees that sum of even a very big number of max'ed out star values 
                        //  can be summed up without overflow
                        starValue = Math.Min(starValue, c_starClip); 
 
                        //  Note: normalized star value is temporary cached into MeasureSize
                        definitions[i].MeasureSize = starValue; 
                        double maxSize = Math.Max(definitions[i].MinSizeForArrange, definitions[i].UserMaxSize);
                        maxSize = Math.Min(maxSize, c_starClip);
                        definitions[i].SizeCache = maxSize / starValue;
                        if (useLayoutRounding) 
                        {
                            roundingErrors[i] = definitions[i].SizeCache; 
                            definitions[i].SizeCache = UIElement.RoundLayoutValue(definitions[i].SizeCache, dpi); 
                        }
                    } 
                    definitionIndices[starDefinitionsCount++] = i;
                }
                else
                { 
                    double userSize = 0;
 
                    switch (definitions[i].UserSize.GridUnitType) 
                    {
                        case (GridUnitType.Pixel): 
                            userSize = definitions[i].UserSize.Value;
                            break;

                        case (GridUnitType.Auto): 
                            userSize = definitions[i].MinSizeForArrange;
                            break; 
                    } 

                    double userMaxSize; 

                    if (definitions[i].IsShared)
                    {
                        //  overriding userMaxSize 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. 
                        userMaxSize = userSize;
                    } 
                    else
                    {
                        userMaxSize = definitions[i].UserMaxSize;
                    } 

                    definitions[i].SizeCache = Math.Max(definitions[i].MinSizeForArrange, Math.Min(userSize, userMaxSize)); 
                    if (useLayoutRounding) 
                    {
                        roundingErrors[i] = definitions[i].SizeCache; 
                        definitions[i].SizeCache = UIElement.RoundLayoutValue(definitions[i].SizeCache, dpi);
                    }

                    allPreferredArrangeSize += definitions[i].SizeCache; 
                    definitionIndices[--nonStarIndex] = i;
                } 
            } 

            //  indices should meet 
            Debug.Assert(nonStarIndex == starDefinitionsCount);

            if (starDefinitionsCount > 0)
            { 
                StarDistributionOrderIndexComparer starDistributionOrderIndexComparer = new StarDistributionOrderIndexComparer(definitions);
                Array.Sort(definitionIndices, 0, starDefinitionsCount, starDistributionOrderIndexComparer); 
 
                //  the 'do {} while' loop below calculates sum of star weights in order to avoid fp overflow...
                //  partial sum value is stored in each definition's SizeCache member. 
                //  this way the algorithm guarantees (starValue <= definition.SizeCache) and thus
                //  (starValue / definition.SizeCache) will never overflow due to sum of star weights becoming zero.
                //  this is an important change from previous implementation where the following was possible:
                //  ((BigValueStar + SmallValueStar) - BigValueStar) resulting in 0... 
                double allStarWeights = 0;
                int i = starDefinitionsCount - 1; 
                do 
                {
                    allStarWeights += definitions[definitionIndices[i]].MeasureSize; 
                    definitions[definitionIndices[i]].SizeCache = allStarWeights;
                } while (--i >= 0);

                i = 0; 
                do
                { 
                    double resolvedSize; 
                    double starValue = definitions[definitionIndices[i]].MeasureSize;
 
                    if (_IsZero(starValue))
                    {
                        resolvedSize = definitions[definitionIndices[i]].MinSizeForArrange;
                    } 
                    else
                    { 
                        double userSize = Math.Max(finalSize - allPreferredArrangeSize, 0.0) * (starValue / definitions[definitionIndices[i]].SizeCache); 
                        resolvedSize = Math.Min(userSize, definitions[definitionIndices[i]].UserMaxSize);
                        resolvedSize = Math.Max(definitions[definitionIndices[i]].MinSizeForArrange, resolvedSize); 
                    }

                    definitions[definitionIndices[i]].SizeCache = resolvedSize;
                    if (useLayoutRounding) 
                    {
                        roundingErrors[definitionIndices[i]] = definitions[definitionIndices[i]].SizeCache; 
                        definitions[definitionIndices[i]].SizeCache = UIElement.RoundLayoutValue(definitions[definitionIndices[i]].SizeCache, dpi); 
                    }
 
                    allPreferredArrangeSize += definitions[definitionIndices[i]].SizeCache;
                } while (++i < starDefinitionsCount);
            }
 
            if (    allPreferredArrangeSize > finalSize
                &&  !_AreClose(allPreferredArrangeSize, finalSize)  ) 
            { 
                DistributionOrderIndexComparer distributionOrderIndexComparer = new DistributionOrderIndexComparer(definitions);
                Array.Sort(definitionIndices, 0, definitions.Length, distributionOrderIndexComparer); 
                double sizeToDistribute = finalSize - allPreferredArrangeSize;

                for (int i = 0; i < definitions.Length; ++i)
                { 
                    int definitionIndex = definitionIndices[i];
                    double final = definitions[definitionIndex].SizeCache + (sizeToDistribute / (definitions.Length - i)); 
                    double finalOld = final; 
                    final = Math.Max(final, definitions[definitionIndex].MinSizeForArrange);
                    final = Math.Min(final, definitions[definitionIndex].SizeCache); 

                    if (useLayoutRounding)
                    {
                        roundingErrors[definitionIndex] = final; 
                        final = UIElement.RoundLayoutValue(finalOld, dpi);
                        final = Math.Max(final, definitions[definitionIndex].MinSizeForArrange); 
                        final = Math.Min(final, definitions[definitionIndex].SizeCache); 
                    }
 
                    sizeToDistribute -= (final - definitions[definitionIndex].SizeCache);
                    definitions[definitionIndex].SizeCache = final;
                }
 
                allPreferredArrangeSize = finalSize - sizeToDistribute;
            } 
 
            if (useLayoutRounding)
            { 
                if (!_AreClose(allPreferredArrangeSize, finalSize))
                {
                    // Compute deltas
                    for (int i = 0; i < definitions.Length; ++i) 
                    {
                        roundingErrors[i] = roundingErrors[i] - definitions[i].SizeCache; 
                        definitionIndices[i] = i; 
                    }
 
                    // Sort rounding errors
                    RoundingErrorIndexComparer roundingErrorIndexComparer = new RoundingErrorIndexComparer(roundingErrors);
                    Array.Sort(definitionIndices, 0, definitions.Length, roundingErrorIndexComparer);
                    double adjustedSize = allPreferredArrangeSize; 
                    double dpiIncrement = UIElement.RoundLayoutValue(1.0, dpi);
 
                    if (allPreferredArrangeSize > finalSize) 
                    {
                        int i = definitions.Length - 1; 
                        while ((adjustedSize > finalSize && !_AreClose(adjustedSize, finalSize)) && i >= 0)
                        {
                            DefinitionBase definition = definitions[definitionIndices[i]];
                            double final = definition.SizeCache - dpiIncrement; 
                            final = Math.Max(final, definition.MinSizeForArrange);
                            if (final < definition.SizeCache) 
                            { 
                                adjustedSize -= dpiIncrement;
                            } 
                            definition.SizeCache = final;
                            i--;
                        }
                    } 
                    else if (allPreferredArrangeSize < finalSize)
                    { 
                        int i = 0; 
                        while ((adjustedSize < finalSize && !_AreClose(adjustedSize, finalSize)) && i < definitions.Length)
                        { 
                            DefinitionBase definition = definitions[definitionIndices[i]];
                            double final = definition.SizeCache + dpiIncrement;
                            final = Math.Max(final, definition.MinSizeForArrange);
                            if (final > definition.SizeCache) 
                            {
                                adjustedSize += dpiIncrement; 
                            } 
                            definition.SizeCache = final;
                            i++; 
                        }
                    }
                }
            } 

            definitions[0].FinalOffset = 0.0; 
            for (int i = 0; i < definitions.Length; ++i) 
            {
                definitions[(i + 1) % definitions.Length].FinalOffset = definitions[i].FinalOffset + definitions[i].SizeCache; 
            }
        }

        ///  
        /// Sorts row/column indices by rounding error if layout rounding is applied.
        ///  
        /// Index, rounding error pair 
        /// Index, rounding error pair
        /// 1 if x.Value > y.Value, 0 if equal, -1 otherwise 
        private static int CompareRoundingErrors(KeyValuePair x, KeyValuePair y)
        {
            if (x.Value < y.Value)
            { 
                return -1;
            } 
            else if (x.Value > y.Value) 
            {
                return 1; 
            }
            return 0;
        }
 
        /// 
        /// Calculates final (aka arrange) size for given range. 
        ///  
        /// Array of definitions to process.
        /// Start of the range. 
        /// Number of items in the range.
        /// Final size.
        private double GetFinalSizeForRange(
            DefinitionBase[] definitions, 
            int start,
            int count) 
        { 
            double size = 0;
            int i = start + count - 1; 

            do
            {
                size += definitions[i].SizeCache; 
            } while (--i >= start);
 
            return (size); 
        }
 
        /// 
        /// Clears dirty state for the grid and its columns / rows
        /// 
        private void SetValid() 
        {
            ExtendedData extData = ExtData; 
            if (extData != null) 
            {
//                for (int i = 0; i < PrivateColumnCount; ++i) DefinitionsU[i].SetValid (); 
//                for (int i = 0; i < PrivateRowCount; ++i) DefinitionsV[i].SetValid ();

                if (extData.TempDefinitions != null)
                { 
                    //  TempDefinitions has to be cleared to avoid "memory leaks"
                    Array.Clear(extData.TempDefinitions, 0, Math.Max(DefinitionsU.Length, DefinitionsV.Length)); 
                    extData.TempDefinitions = null; 
                }
            } 
        }

        /// 
        /// Returns true if ColumnDefinitions collection is not empty 
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)] 
        public bool ShouldSerializeColumnDefinitions() 
        {
            ExtendedData extData = ExtData; 
            return (    extData != null
                    &&  extData.ColumnDefinitions != null
                    &&  extData.ColumnDefinitions.Count > 0   );
        } 

        ///  
        /// Returns true if RowDefinitions collection is not empty 
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)] 
        public bool ShouldSerializeRowDefinitions()
        {
            ExtendedData extData = ExtData;
            return (    extData != null 
                    &&  extData.RowDefinitions != null
                    &&  extData.RowDefinitions.Count > 0  ); 
        } 

        ///  
        /// Synchronized ShowGridLines property with the state of the grid's visual collection
        /// by adding / removing GridLinesRenderer visual.
        /// Returns a reference to GridLinesRenderer visual or null.
        ///  
        private GridLinesRenderer EnsureGridLinesRenderer()
        { 
            // 
            //  synchronize the state
            // 
            if (ShowGridLines && (_gridLinesRenderer == null))
            {
                _gridLinesRenderer = new GridLinesRenderer();
                this.AddVisualChild(_gridLinesRenderer); 
            }
 
            if ((!ShowGridLines) && (_gridLinesRenderer != null)) 
            {
                this.RemoveVisualChild(_gridLinesRenderer); 
                _gridLinesRenderer = null;
            }

            return (_gridLinesRenderer); 
        }
 
        ///  
        /// 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); 
        }
 
        ///  
        /// CheckFlagsOr returns true if at least one flag in the
        /// given bitmask is set. 
        /// 
        /// 
        /// If no bits are set in the given bitmask, the method returns
        /// true. 
        /// 
        private bool CheckFlagsOr(Flags flags) 
        { 
            return (flags == 0 || (_flags & flags) != 0);
        } 

        /// 
        /// 
        ///  
        private static void OnShowGridLinesPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            Grid grid = (Grid)d; 

            if (    grid.ExtData != null    // trivial grid is 1 by 1. there is no grid lines anyway 
                &&  grid.ListenToNotifications)
            {
                grid.InvalidateVisual();
            } 

            grid.SetFlags((bool) e.NewValue, Flags.ShowGridLinesPropertyValue); 
        } 

        ///  
        /// 
        /// 
        private static void OnCellAttachedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            Visual child = d as Visual;
 
            if (child != null) 
            {
                Grid grid = VisualTreeHelper.GetParent(child) as Grid; 
                if (    grid != null
                    &&  grid.ExtData != null
                    &&  grid.ListenToNotifications  )
                { 
                    grid.CellsStructureDirty = true;
                    grid.InvalidateMeasure(); 
                } 
            }
        } 

        /// 
        /// 
        ///  
        private static bool IsIntValueNotNegative(object value)
        { 
            return ((int)value >= 0); 
        }
 
        /// 
        /// 
        /// 
        private static bool IsIntValueGreaterThanZero(object value) 
        {
            return ((int)value > 0); 
        } 

        ///  
        /// Helper for Comparer methods.
        /// 
        /// 
        /// true iff one or both of x and y are null, in which case result holds 
        /// the relative sort order.
        ///  
        private static bool CompareNullRefs(object x, object y, out int result) 
        {
            result = 2; 

            if (x == null)
            {
                if (y == null) 
                {
                    result = 0; 
                } 
                else
                { 
                    result = -1;
                }
            }
            else 
            {
                if (y == null) 
                { 
                    result = 1;
                } 
            }

            return (result != 2);
        } 

        #endregion Private Methods 
 
        //------------------------------------------------------
        // 
        //  Private Properties
        //
        //-----------------------------------------------------
 
        #region Private Properties
 
        ///  
        /// Private version returning array of column definitions.
        ///  
        private DefinitionBase[] DefinitionsU
        {
            get { return (ExtData.DefinitionsU); }
        } 

        ///  
        /// Private version returning array of row definitions. 
        /// 
        private DefinitionBase[] DefinitionsV 
        {
            get { return (ExtData.DefinitionsV); }
        }
 
        /// 
        /// Helper accessor to layout time array of definitions. 
        ///  
        private DefinitionBase[] TempDefinitions
        { 
            get
            {
                ExtendedData extData = ExtData;
 
                if (extData.TempDefinitions == null)
                { 
                    int requiredLength = Math.Max(DefinitionsU.Length, DefinitionsV.Length); 
                    WeakReference tempDefinitionsWeakRef = (WeakReference)Thread.GetData(s_tempDefinitionsDataSlot);
                    if (tempDefinitionsWeakRef == null) 
                    {
                        extData.TempDefinitions = new DefinitionBase[requiredLength * 2];
                        Thread.SetData(s_tempDefinitionsDataSlot, new WeakReference(extData.TempDefinitions));
                    } 
                    else
                    { 
                        extData.TempDefinitions = (DefinitionBase[])tempDefinitionsWeakRef.Target; 
                        if (    extData.TempDefinitions == null
                            ||  extData.TempDefinitions.Length < requiredLength   ) 
                        {
                            extData.TempDefinitions = new DefinitionBase[requiredLength * 2];
                            tempDefinitionsWeakRef.Target = extData.TempDefinitions;
                        } 
                    }
                } 
                return (extData.TempDefinitions); 
            }
        } 

        /// 
        /// Helper accessor to definition indices.
        ///  
        private int[] DefinitionIndices
        { 
            get 
            {
                int requiredLength = Math.Max(DefinitionsU.Length, DefinitionsV.Length); 

                if (_definitionIndices == null && requiredLength == 0)
                {
                    _definitionIndices = new int[1]; 
                }
                else if (_definitionIndices == null || _definitionIndices.Length < requiredLength) 
                { 
                    _definitionIndices = new int[requiredLength];
                } 

                return _definitionIndices;
            }
        } 

        ///  
        /// Helper accessor to rounding errors. 
        /// 
        private double[] RoundingErrors 
        {
            get
            {
                int requiredLength = Math.Max(DefinitionsU.Length, DefinitionsV.Length); 

                if (_roundingErrors == null && requiredLength == 0) 
                { 
                    _roundingErrors = new double[1];
                } 
                else if (_roundingErrors == null || _roundingErrors.Length < requiredLength)
                {
                    _roundingErrors = new double[requiredLength];
                } 
                return _roundingErrors;
            } 
        } 

        ///  
        /// Private version returning array of cells.
        /// 
        private CellCache[] PrivateCells
        { 
            get { return (ExtData.CellCachesCollection); }
        } 
 
        /// 
        /// Convenience accessor to ValidCellsStructure bit flag. 
        /// 
        private bool CellsStructureDirty
        {
            get { return (!CheckFlagsAnd(Flags.ValidCellsStructure)); } 
            set { SetFlags(!value, Flags.ValidCellsStructure); }
        } 
 
        /// 
        /// Convenience accessor to ListenToNotifications bit flag. 
        /// 
        private bool ListenToNotifications
        {
            get { return (CheckFlagsAnd(Flags.ListenToNotifications)); } 
            set { SetFlags(value, Flags.ListenToNotifications); }
        } 
 
        /// 
        /// Convenience accessor to SizeToContentU bit flag. 
        /// 
        private bool SizeToContentU
        {
            get { return (CheckFlagsAnd(Flags.SizeToContentU)); } 
            set { SetFlags(value, Flags.SizeToContentU); }
        } 
 
        /// 
        /// Convenience accessor to SizeToContentV bit flag. 
        /// 
        private bool SizeToContentV
        {
            get { return (CheckFlagsAnd(Flags.SizeToContentV)); } 
            set { SetFlags(value, Flags.SizeToContentV); }
        } 
 
        /// 
        /// Convenience accessor to HasStarCellsU bit flag. 
        /// 
        private bool HasStarCellsU
        {
            get { return (CheckFlagsAnd(Flags.HasStarCellsU)); } 
            set { SetFlags(value, Flags.HasStarCellsU); }
        } 
 
        /// 
        /// Convenience accessor to HasStarCellsV bit flag. 
        /// 
        private bool HasStarCellsV
        {
            get { return (CheckFlagsAnd(Flags.HasStarCellsV)); } 
            set { SetFlags(value, Flags.HasStarCellsV); }
        } 
 
        /// 
        /// Convenience accessor to HasGroup3CellsInAutoRows bit flag. 
        /// 
        private bool HasGroup3CellsInAutoRows
        {
            get { return (CheckFlagsAnd(Flags.HasGroup3CellsInAutoRows)); } 
            set { SetFlags(value, Flags.HasGroup3CellsInAutoRows); }
        } 
 
        /// 
        /// fp version of d == 0. 
        /// 
        /// Value to check.
        /// true if d == 0.
        private static bool _IsZero(double d) 
        {
            return (Math.Abs(d) < c_epsilon); 
        } 

        ///  
        /// fp version of d1 == d2
        /// 
        /// First value to compare
        /// Second value to compare 
        /// true if d1 == d2
        private static bool _AreClose(double d1, double d2) 
        { 
            return (Math.Abs(d1 - d2) < c_epsilon);
        } 

        /// 
        /// Returns reference to extended data bag.
        ///  
        private ExtendedData ExtData
        { 
            get { return (_data); } 
        }
 
        #endregion Private Properties

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

        #region Private Fields 
        private ExtendedData _data;                             //  extended data instantiated on demand, for non-trivial case handling only
        private Flags _flags;                                   //  grid validity / property caches dirtiness flags
        private GridLinesRenderer _gridLinesRenderer;
 
        // Keeps track of definition indices.
        int[] _definitionIndices; 
 
        // Stores unrounded values and rounding errors during layout rounding.
        double[] _roundingErrors; 

        #endregion Private Fields

        //----------------------------------------------------- 
        //
        //  Static Fields 
        // 
        //-----------------------------------------------------
 
        #region Static Fields
        private const double c_epsilon = 1e-5;                  //  used in fp calculations
        private const double c_starClip = 1e298;                //  used as maximum for clipping star values during normalization
        private static readonly LocalDataStoreSlot s_tempDefinitionsDataSlot = Thread.AllocateDataSlot(); 
        private static readonly IComparer s_spanPreferredDistributionOrderComparer = new SpanPreferredDistributionOrderComparer();
        private static readonly IComparer s_spanMaxDistributionOrderComparer = new SpanMaxDistributionOrderComparer(); 
        private static readonly IComparer s_starDistributionOrderComparer = new StarDistributionOrderComparer(); 
        private static readonly IComparer s_distributionOrderComparer = new DistributionOrderComparer();
 
        #endregion Static Fields

        //------------------------------------------------------
        // 
        //  Private Structures / Classes
        // 
        //----------------------------------------------------- 

        #region Private Structures Classes 

        /// 
        /// Extended data instantiated on demand, when grid handles non-trivial case.
        ///  
        private class ExtendedData
        { 
            internal ColumnDefinitionCollection ColumnDefinitions;  //  collection of column definitions (logical tree support) 
            internal RowDefinitionCollection RowDefinitions;        //  collection of row definitions (logical tree support)
            internal DefinitionBase[] DefinitionsU;                 //  collection of column definitions used during calc 
            internal DefinitionBase[] DefinitionsV;                 //  collection of row definitions used during calc
            internal CellCache[] CellCachesCollection;              //  backing store for logical children
            internal int CellGroup1;                                //  index of the first cell in first cell group
            internal int CellGroup2;                                //  index of the first cell in second cell group 
            internal int CellGroup3;                                //  index of the first cell in third cell group
            internal int CellGroup4;                                //  index of the first cell in forth cell group 
            internal DefinitionBase[] TempDefinitions;              //  temporary array used during layout for various purposes 
                                                                    //  TempDefinitions.Length == Max(definitionsU.Length, definitionsV.Length)
        } 

        /// 
        /// Grid validity / property caches dirtiness flags
        ///  
        [System.Flags]
        private enum Flags 
        { 
            //
            //  the foolowing flags let grid tracking dirtiness in more granular manner: 
            //  * Valid???Structure flags indicate that elements were added or removed.
            //  * Valid???Layout flags indicate that layout time portion of the information
            //    stored on the objects should be updated.
            // 
            ValidDefinitionsUStructure              = 0x00000001,
            ValidDefinitionsVStructure              = 0x00000002, 
            ValidCellsStructure                     = 0x00000004, 

            // 
            //  boolean properties state
            //
            ShowGridLinesPropertyValue              = 0x00000100,   //  show grid lines ?
 
            //
            //  boolean flags 
            // 
            ListenToNotifications                   = 0x00001000,   //  "0" when all notifications are ignored
            SizeToContentU                          = 0x00002000,   //  "1" if calculating to content in U direction 
            SizeToContentV                          = 0x00004000,   //  "1" if calculating to content in V direction
            HasStarCellsU                           = 0x00008000,   //  "1" if at least one cell belongs to a Star column
            HasStarCellsV                           = 0x00010000,   //  "1" if at least one cell belongs to a Star row
            HasGroup3CellsInAutoRows                = 0x00020000,   //  "1" if at least one cell of group 3 belongs to an Auto row 
            MeasureOverrideInProgress               = 0x00040000,   //  "1" while in the context of Grid.MeasureOverride
            ArrangeOverrideInProgress               = 0x00080000,   //  "1" while in the context of Grid.ArrangeOverride 
        } 

        #endregion Private Structures Classes 

        //------------------------------------------------------
        //
        //  Properties 
        //
        //------------------------------------------------------ 
 
        #region Properties
 
        /// 
        /// ShowGridLines property. This property is used mostly
        /// for simplification of visual debuggig. When it is set
        /// to true grid lines are drawn to visualize location 
        /// of grid lines.
        ///  
        public static readonly DependencyProperty ShowGridLinesProperty = 
                DependencyProperty.Register(
                      "ShowGridLines", 
                      typeof(bool),
                      typeof(Grid),
                      new FrameworkPropertyMetadata(
                              false, 
                              new PropertyChangedCallback(OnShowGridLinesPropertyChanged)));
 
        ///  
        /// Column property. This is an attached property.
        /// Grid defines Column property, so that it can be set 
        /// on any element treated as a cell. Column property
        /// specifies child's position with respect to columns.
        /// 
        ///  
        ///  Columns are 0 - based. In order to appear in first column, element
        /// should have Column property set to 0.  
        ///  Default value for the property is 0.  
        /// 
        [CommonDependencyProperty] 
        public static readonly DependencyProperty ColumnProperty =
                DependencyProperty.RegisterAttached(
                      "Column",
                      typeof(int), 
                      typeof(Grid),
                      new FrameworkPropertyMetadata( 
                              0, 
                              new PropertyChangedCallback(OnCellAttachedPropertyChanged)),
                      new ValidateValueCallback(IsIntValueNotNegative)); 

        /// 
        /// Row property. This is an attached property.
        /// Grid defines Row, so that it can be set 
        /// on any element treated as a cell. Row property
        /// specifies child's position with respect to rows. 
        ///  
        ///  Rows are 0 - based. In order to appear in first row, element
        /// should have Row property set to 0.  
        ///  Default value for the property is 0. 
        /// 
        /// 
        [CommonDependencyProperty] 
        public static readonly DependencyProperty RowProperty =
                DependencyProperty.RegisterAttached( 
                      "Row", 
                      typeof(int),
                      typeof(Grid), 
                      new FrameworkPropertyMetadata(
                              0,
                              new PropertyChangedCallback(OnCellAttachedPropertyChanged)),
                      new ValidateValueCallback(IsIntValueNotNegative)); 

        ///  
        /// ColumnSpan property. This is an attached property. 
        /// Grid defines ColumnSpan, so that it can be set
        /// on any element treated as a cell. ColumnSpan property 
        /// specifies child's width with respect to columns.
        /// Example, ColumnSpan == 2 means that child will span across two columns.
        /// 
        ///  
        /// Default value for the property is 1.
        ///  
        [CommonDependencyProperty] 
        public static readonly DependencyProperty ColumnSpanProperty =
                DependencyProperty.RegisterAttached( 
                      "ColumnSpan",
                      typeof(int),
                      typeof(Grid),
                      new FrameworkPropertyMetadata( 
                              1,
                              new PropertyChangedCallback(OnCellAttachedPropertyChanged)), 
                      new ValidateValueCallback(IsIntValueGreaterThanZero)); 

        ///  
        /// RowSpan property. This is an attached property.
        /// Grid defines RowSpan, so that it can be set
        /// on any element treated as a cell. RowSpan property
        /// specifies child's height with respect to row grid lines. 
        /// Example, RowSpan == 3 means that child will span across three rows.
        ///  
        ///  
        /// Default value for the property is 1.
        ///  
        [CommonDependencyProperty]
        public static readonly DependencyProperty RowSpanProperty =
                DependencyProperty.RegisterAttached(
                      "RowSpan", 
                      typeof(int),
                      typeof(Grid), 
                      new FrameworkPropertyMetadata( 
                              1,
                              new PropertyChangedCallback(OnCellAttachedPropertyChanged)), 
                      new ValidateValueCallback(IsIntValueGreaterThanZero));


        ///  
        /// IsSharedSizeScope property marks scoping element for shared size.
        ///  
        public static readonly DependencyProperty IsSharedSizeScopeProperty  = 
                DependencyProperty.RegisterAttached(
                      "IsSharedSizeScope", 
                      typeof(bool),
                      typeof(Grid),
                      new FrameworkPropertyMetadata(
                              false, 
                              new PropertyChangedCallback(DefinitionBase.OnIsSharedSizeScopePropertyChanged)));
 
        #endregion Properties 

        //----------------------------------------------------- 
        //
        //  Internal Structures / Classes
        //
        //------------------------------------------------------ 

        #region Internal Structures Classes 
 
        /// 
        /// LayoutTimeSizeType is used internally and reflects layout-time size type. 
        /// 
        [System.Flags]
        internal enum LayoutTimeSizeType : byte
        { 
            None        = 0x00,
            Pixel       = 0x01, 
            Auto        = 0x02, 
            Star        = 0x04,
        } 

        #endregion Internal Structures Classes

        //----------------------------------------------------- 
        //
        //  Private Structures / Classes 
        // 
        //-----------------------------------------------------
 
        #region Private Structures Classes

        /// 
        /// CellCache stored calculated values of 
        /// 1. attached cell positioning properties;
        /// 2. size type; 
        /// 3. index of a next cell in the group; 
        /// 
        private struct CellCache 
        {
            internal int ColumnIndex;
            internal int RowIndex;
            internal int ColumnSpan; 
            internal int RowSpan;
            internal LayoutTimeSizeType SizeTypeU; 
            internal LayoutTimeSizeType SizeTypeV; 
            internal int Next;
            internal bool IsStarU { get { return ((SizeTypeU & LayoutTimeSizeType.Star) != 0); } } 
            internal bool IsAutoU { get { return ((SizeTypeU & LayoutTimeSizeType.Auto) != 0); } }
            internal bool IsStarV { get { return ((SizeTypeV & LayoutTimeSizeType.Star) != 0); } }
            internal bool IsAutoV { get { return ((SizeTypeV & LayoutTimeSizeType.Auto) != 0); } }
        } 

        ///  
        /// Helper class for representing a key for a span in hashtable. 
        /// 
        private class SpanKey 
        {
            /// 
            /// Constructor.
            ///  
            /// Starting index of the span.
            /// Span count. 
            /// true for columns; false for rows. 
            internal SpanKey(int start, int count, bool u)
            { 
                _start = start;
                _count = count;
                _u = u;
            } 

            ///  
            ///  
            /// 
            public override int GetHashCode() 
            {
                int hash = (_start ^ (_count << 2));

                if (_u) hash &= 0x7ffffff; 
                else    hash |= 0x8000000;
 
                return (hash); 
            }
 
            /// 
            /// 
            /// 
            public override bool Equals(object obj) 
            {
                SpanKey sk = obj as SpanKey; 
                return (    sk != null 
                        &&  sk._start == _start
                        &&  sk._count == _count 
                        &&  sk._u == _u );
            }

            ///  
            /// Returns start index of the span.
            ///  
            internal int Start { get { return (_start); } } 

            ///  
            /// Returns span count.
            /// 
            internal int Count { get { return (_count); } }
 
            /// 
            /// Returns true if this is a column span. 
            /// false if this is a row span. 
            /// 
            internal bool U { get { return (_u); } } 

            private int _start;
            private int _count;
            private bool _u; 
        }
 
        ///  
        /// SpanPreferredDistributionOrderComparer.
        ///  
        private class SpanPreferredDistributionOrderComparer : IComparer
        {
            public int Compare(object x, object y)
            { 
                DefinitionBase definitionX = x as DefinitionBase;
                DefinitionBase definitionY = y as DefinitionBase; 
 
                int result;
 
                if (!CompareNullRefs(definitionX, definitionY, out result))
                {
                    if (definitionX.UserSize.IsAuto)
                    { 
                        if (definitionY.UserSize.IsAuto)
                        { 
                            result = definitionX.MinSize.CompareTo(definitionY.MinSize); 
                        }
                        else 
                        {
                            result = -1;
                        }
                    } 
                    else
                    { 
                        if (definitionY.UserSize.IsAuto) 
                        {
                            result = +1; 
                        }
                        else
                        {
                            result = definitionX.PreferredSize.CompareTo(definitionY.PreferredSize); 
                        }
                    } 
                } 

                return result; 
            }
        }

        ///  
        /// SpanMaxDistributionOrderComparer.
        ///  
        private class SpanMaxDistributionOrderComparer : IComparer 
        {
            public int Compare(object x, object y) 
            {
                DefinitionBase definitionX = x as DefinitionBase;
                DefinitionBase definitionY = y as DefinitionBase;
 
                int result;
 
                if (!CompareNullRefs(definitionX, definitionY, out result)) 
                {
                    if (definitionX.UserSize.IsAuto) 
                    {
                        if (definitionY.UserSize.IsAuto)
                        {
                            result = definitionX.SizeCache.CompareTo(definitionY.SizeCache); 
                        }
                        else 
                        { 
                            result = +1;
                        } 
                    }
                    else
                    {
                        if (definitionY.UserSize.IsAuto) 
                        {
                            result = -1; 
                        } 
                        else
                        { 
                            result = definitionX.SizeCache.CompareTo(definitionY.SizeCache);
                        }
                    }
                } 

                return result; 
            } 
        }
 
        /// 
        /// StarDistributionOrderComparer.
        /// 
        private class StarDistributionOrderComparer : IComparer 
        {
            public int Compare(object x, object y) 
            { 
                DefinitionBase definitionX = x as DefinitionBase;
                DefinitionBase definitionY = y as DefinitionBase; 

                int result;

                if (!CompareNullRefs(definitionX, definitionY, out result)) 
                {
                    result = definitionX.SizeCache.CompareTo(definitionY.SizeCache); 
                } 

                return result; 
            }
        }

        ///  
        /// DistributionOrderComparer.
        ///  
        private class DistributionOrderComparer: IComparer 
        {
            public int Compare(object x, object y) 
            {
                DefinitionBase definitionX = x as DefinitionBase;
                DefinitionBase definitionY = y as DefinitionBase;
 
                int result;
 
                if (!CompareNullRefs(definitionX, definitionY, out result)) 
                {
                    double xprime = definitionX.SizeCache - definitionX.MinSizeForArrange; 
                    double yprime = definitionY.SizeCache - definitionY.MinSizeForArrange;
                    result = xprime.CompareTo(yprime);
                }
 
                return result;
            } 
        } 

 
        /// 
        /// StarDistributionOrderIndexComparer.
        /// 
        private class StarDistributionOrderIndexComparer : IComparer 
        {
            private readonly DefinitionBase[] definitions; 
 
            internal StarDistributionOrderIndexComparer(DefinitionBase[] definitions)
            { 
                Invariant.Assert(definitions != null);
                this.definitions = definitions;
            }
 
            public int Compare(object x, object y)
            { 
                int? indexX = x as int?; 
                int? indexY = y as int?;
 
                DefinitionBase definitionX = null;
                DefinitionBase definitionY = null;

                if (indexX != null) 
                {
                    definitionX = definitions[indexX.Value]; 
                } 
                if (indexY != null)
                { 
                    definitionY = definitions[indexY.Value];
                }

                int result; 

                if (!CompareNullRefs(definitionX, definitionY, out result)) 
                { 
                    result = definitionX.SizeCache.CompareTo(definitionY.SizeCache);
                } 

                return result;
            }
        } 

        ///  
        /// DistributionOrderComparer. 
        /// 
        private class DistributionOrderIndexComparer : IComparer 
        {
            private readonly DefinitionBase[] definitions;

            internal DistributionOrderIndexComparer(DefinitionBase[] definitions) 
            {
                Invariant.Assert(definitions != null); 
                this.definitions = definitions; 
            }
 
            public int Compare(object x, object y)
            {
                int? indexX = x as int?;
                int? indexY = y as int?; 

                DefinitionBase definitionX = null; 
                DefinitionBase definitionY = null; 

                if (indexX != null) 
                {
                    definitionX = definitions[indexX.Value];
                }
                if (indexY != null) 
                {
                    definitionY = definitions[indexY.Value]; 
                } 

                int result; 

                if (!CompareNullRefs(definitionX, definitionY, out result))
                {
                    double xprime = definitionX.SizeCache - definitionX.MinSizeForArrange; 
                    double yprime = definitionY.SizeCache - definitionY.MinSizeForArrange;
                    result = xprime.CompareTo(yprime); 
                } 

                return result; 
            }
        }

        ///  
        /// RoundingErrorIndexComparer.
        ///  
        private class RoundingErrorIndexComparer : IComparer 
        {
            private readonly double[] errors; 

            internal RoundingErrorIndexComparer(double[] errors)
            {
                Invariant.Assert(errors != null); 
                this.errors = errors;
            } 
 
            public int Compare(object x, object y)
            { 
                int? indexX = x as int?;
                int? indexY = y as int?;

                int result; 

                if (!CompareNullRefs(indexX, indexY, out result)) 
                { 
                    double errorX = errors[indexX.Value];
                    double errorY = errors[indexY.Value]; 
                    result = errorX.CompareTo(errorY);
                }

                return result; 
            }
        } 
 
        /// 
        /// Implementation of a simple enumerator of grid's logical children 
        /// 
        private class GridChildrenCollectionEnumeratorSimple : IEnumerator
        {
            internal GridChildrenCollectionEnumeratorSimple(Grid grid, bool includeChildren) 
            {
                Debug.Assert(grid != null); 
                _currentEnumerator = -1; 
                _enumerator0 = new ColumnDefinitionCollection.Enumerator(grid.ExtData != null ? grid.ExtData.ColumnDefinitions : null);
                _enumerator1 = new RowDefinitionCollection.Enumerator(grid.ExtData != null ? grid.ExtData.RowDefinitions : null); 
                // GridLineRenderer is NOT included into this enumerator.
                _enumerator2Index = 0;
                if (includeChildren)
                { 
                    _enumerator2Collection = grid.Children;
                    _enumerator2Count = _enumerator2Collection.Count; 
                } 
                else
                { 
                    _enumerator2Collection = null;
                    _enumerator2Count = 0;
                }
            } 

            public bool MoveNext() 
            { 
                while (_currentEnumerator < 3)
                { 
                    if (_currentEnumerator >= 0)
                    {
                        switch (_currentEnumerator)
                        { 
                            case (0): if (_enumerator0.MoveNext()) { _currentChild = _enumerator0.Current; return (true); } break;
                            case (1): if (_enumerator1.MoveNext()) { _currentChild = _enumerator1.Current; return (true); } break; 
                            case (2): if (_enumerator2Index < _enumerator2Count) 
                                      {
                                          _currentChild = _enumerator2Collection[_enumerator2Index]; 
                                          _enumerator2Index++;
                                          return (true);
                                      }
                                      break; 
                        }
                    } 
                    _currentEnumerator++; 
                }
                return (false); 
            }

            public Object Current
            { 
                get
                { 
                    if (_currentEnumerator == -1) 
                    {
                        #pragma warning suppress 6503 // IEnumerator.Current is documented to throw this exception 
                        throw new InvalidOperationException(SR.Get(SRID.EnumeratorNotStarted));
                    }
                    if (_currentEnumerator >= 3)
                    { 
                        #pragma warning suppress 6503 // IEnumerator.Current is documented to throw this exception
                        throw new InvalidOperationException(SR.Get(SRID.EnumeratorReachedEnd)); 
                    } 

                    //  assert below is not true anymore since UIElementCollection allowes for null children 
                    //Debug.Assert(_currentChild != null);
                    return (_currentChild);
                }
            } 

            public void Reset() 
            { 
                _currentEnumerator = -1;
                _currentChild = null; 
                _enumerator0.Reset();
                _enumerator1.Reset();
                _enumerator2Index = 0;
            } 

            private int _currentEnumerator; 
            private Object _currentChild; 
            private ColumnDefinitionCollection.Enumerator _enumerator0;
            private RowDefinitionCollection.Enumerator _enumerator1; 
            private UIElementCollection _enumerator2Collection;
            private int _enumerator2Index;
            private int _enumerator2Count;
        } 

        ///  
        /// Helper to render grid lines. 
        /// 
        internal class GridLinesRenderer : DrawingVisual 
        {
            /// 
            /// Static initialization
            ///  
            static GridLinesRenderer()
            { 
                s_oddDashPen = new Pen(Brushes.Blue, c_penWidth); 
                DoubleCollection oddDashArray = new DoubleCollection();
                oddDashArray.Add(c_dashLength); 
                oddDashArray.Add(c_dashLength);
                s_oddDashPen.DashStyle = new DashStyle(oddDashArray, 0);
                s_oddDashPen.DashCap = PenLineCap.Flat;
                s_oddDashPen.Freeze(); 

                s_evenDashPen = new Pen(Brushes.Yellow, c_penWidth); 
                DoubleCollection evenDashArray = new DoubleCollection(); 
                evenDashArray.Add(c_dashLength);
                evenDashArray.Add(c_dashLength); 
                s_evenDashPen.DashStyle = new DashStyle(evenDashArray, c_dashLength);
                s_evenDashPen.DashCap = PenLineCap.Flat;
                s_evenDashPen.Freeze();
            } 

            ///  
            /// UpdateRenderBounds. 
            /// 
            /// Size of render bounds 
            internal void UpdateRenderBounds(Size boundsSize)
            {
                using (DrawingContext drawingContext = RenderOpen())
                { 
                    Grid grid = VisualTreeHelper.GetParent(this) as Grid;
                    if (    grid == null 
                        ||  grid.ShowGridLines == false ) 
                    {
                        return; 
                    }

                    for (int i = 1; i < grid.DefinitionsU.Length; ++i)
                    { 
                        DrawGridLine(
                            drawingContext, 
                            grid.DefinitionsU[i].FinalOffset, 0.0, 
                            grid.DefinitionsU[i].FinalOffset, boundsSize.Height);
                    } 

                    for (int i = 1; i < grid.DefinitionsV.Length; ++i)
                    {
                        DrawGridLine( 
                            drawingContext,
                            0.0, grid.DefinitionsV[i].FinalOffset, 
                            boundsSize.Width, grid.DefinitionsV[i].FinalOffset); 
                    }
                } 
            }

            /// 
            /// Draw single hi-contrast line. 
            /// 
            private static void DrawGridLine( 
                DrawingContext drawingContext, 
                double startX,
                double startY, 
                double endX,
                double endY)
            {
                Point start = new Point(startX, startY); 
                Point end = new Point(endX, endY);
                drawingContext.DrawLine(s_oddDashPen, start, end); 
                drawingContext.DrawLine(s_evenDashPen, start, end); 
            }
 
            private const double c_dashLength = 4.0;    //
            private const double c_penWidth = 1.0;      //
            private static readonly Pen s_oddDashPen;   //  first pen to draw dash
            private static readonly Pen s_evenDashPen;  //  second pen to draw dash 
            private static readonly Point c_zeroPoint = new Point(0, 0);
        } 
 
        #endregion Private Structures Classes
 
        //-----------------------------------------------------
        //
        //  Extended debugging for grid
        // 
        //------------------------------------------------------
 
#if GRIDPARANOIA 
        private static double _performanceFrequency;
        private static readonly bool _performanceFrequencyInitialized = InitializePerformanceFrequency(); 

        //CASRemoval:[System.Security.SuppressUnmanagedCodeSecurity, System.Runtime.InteropServices.DllImport("kernel32.dll")]
        private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
 
        //CASRemoval:[System.Security.SuppressUnmanagedCodeSecurity, System.Runtime.InteropServices.DllImport("kernel32.dll")]
        private static extern bool QueryPerformanceFrequency(out long lpFrequency); 
 
        private static double CostInMilliseconds(long count)
        { 
            return ((double)count / _performanceFrequency);
        }

        private static long Cost(long startCount, long endCount) 
        {
            long l = endCount - startCount; 
            if (l < 0)  { l += long.MaxValue;   } 
            return (l);
        } 

        private static bool InitializePerformanceFrequency()
        {
            long l; 
            QueryPerformanceFrequency(out l);
            _performanceFrequency = (double)l * 0.001; 
            return (true); 
        }
 
        private struct Counter
        {
            internal long   Start;
            internal long   Total; 
            internal int    Calls;
        } 
 
        private Counter[] _counters;
        private bool _hasNewCounterInfo; 
#endif // GRIDPARANOIA

        //
        //  This property 
        //  1. Finds the correct initial size for the _effectiveValues store on the current DependencyObject
        //  2. This is a performance optimization 
        // 
        internal override int EffectiveValuesInitialSize
        { 
            get { return 9; }
        }

        [Conditional("GRIDPARANOIA")] 
        internal void EnterCounterScope(Counters scopeCounter)
        { 
            #if GRIDPARANOIA 
            if (ID == "CountThis")
            { 
                if (_counters == null)
                {
                    _counters = new Counter[(int)Counters.Count];
                } 
                ExitCounterScope(Counters.Default);
                EnterCounter(scopeCounter); 
            } 
            else
            { 
                _counters = null;
            }
            #endif // GRIDPARANOIA
        } 

        [Conditional("GRIDPARANOIA")] 
        internal void ExitCounterScope(Counters scopeCounter) 
        {
            #if GRIDPARANOIA 
            if (_counters != null)
            {
                if (scopeCounter != Counters.Default)
                { 
                    ExitCounter(scopeCounter);
                } 
 
                if (_hasNewCounterInfo)
                { 
                    string NFormat = "F6";
                    Console.WriteLine(
                                "\ncounter name          | total t (ms)  | # of calls    | per call t (ms)"
                            +   "\n----------------------+---------------+---------------+----------------------" ); 

                    for (int i = 0; i < _counters.Length; ++i) 
                    { 
                        if (_counters[i].Calls > 0)
                        { 
                            Counters counter = (Counters)i;
                            double total = CostInMilliseconds(_counters[i].Total);
                            double single = total / _counters[i].Calls;
                            string counterName = counter.ToString(); 
                            string separator;
 
                            if (counterName.Length < 8)         { separator = "\t\t\t";  } 
                            else if (counterName.Length < 16)   { separator = "\t\t";    }
                            else                                { separator = "\t";      } 

                            Console.WriteLine(
                                    counter.ToString() + separator
                                +   total.ToString(NFormat) + "\t" 
                                +   _counters[i].Calls + "\t\t"
                                +   single.ToString(NFormat)); 
 
                            _counters[i] = new Counter();
                        } 
                    }
                }
                _hasNewCounterInfo = false;
            } 
            #endif // GRIDPARANOIA
        } 
 
        [Conditional("GRIDPARANOIA")]
        internal void EnterCounter(Counters counter) 
        {
            #if GRIDPARANOIA
            if (_counters != null)
            { 
                Debug.Assert((int)counter < _counters.Length);
 
                int i = (int)counter; 
                QueryPerformanceCounter(out _counters[i].Start);
            } 
            #endif // GRIDPARANOIA
        }

        [Conditional("GRIDPARANOIA")] 
        internal void ExitCounter(Counters counter)
        { 
            #if GRIDPARANOIA 
            if (_counters != null)
            { 
                Debug.Assert((int)counter < _counters.Length);

                int i = (int)counter;
                long l; 
                QueryPerformanceCounter(out l);
                l = Cost(_counters[i].Start, l); 
                _counters[i].Total += l; 
                _counters[i].Calls++;
                _hasNewCounterInfo = true; 
            }
            #endif // GRIDPARANOIA
        }
 
        internal enum Counters : int
        { 
            Default = -1, 

            MeasureOverride, 
            _ValidateColsStructure,
            _ValidateRowsStructure,
            _ValidateCells,
            _MeasureCell, 
            __MeasureChild,
            _CalculateDesiredSize, 
 
            ArrangeOverride,
            _SetFinalSize, 
            _ArrangeChildHelper2,
            _PositionCell,

            Count, 
        }
    } 
} 

 



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