Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / Controls / Grid.cs / 1 / Grid.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: Grid implementation. // // Specs // Grid : [....]/layout/Specs/Grid.mht // Size Sharing: [....]/layout/Specs/Size%20Information%20Sharing.doc // // Misc // Grid Tutorial: [....]/layout/Documentation%20and%20Tutorials/Grid%20Tutorial.mht // // History: // 09/24/2003 : [....] - Created (in griddy prototype branch); // 10/27/2003 : [....] - Ported from griddy prototype branch; // 01/20/2004 : [....] - 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.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) { 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); 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); SetFinalSize(DefinitionsV, arrangeSize.Height); 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(children[i].DesiredSize.Width); } 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(children[i].DesiredSize.Height); } 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) { child.Measure(new Size(cellMeasureWidth, cellMeasureHeight)); } 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. private void SetFinalSize( DefinitionBase[] definitions, double finalSize) { DefinitionBase[] tempDefinitions = TempDefinitions; // temp array used to remember definitions indices int starDefinitionsCount = 0; // traverses form the first entry up int nonStarIndex = definitions.Length; // traverses from the last entry down double allPreferredArrangeSize = 0; 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) { tempDefinitions[starDefinitionsCount++] = definitions[i]; 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; } } else { tempDefinitions[--nonStarIndex] = definitions[i]; 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)); allPreferredArrangeSize += definitions[i].SizeCache; } } // indices should meet Debug.Assert(nonStarIndex == starDefinitionsCount); 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].MinSizeForArrange; } else { double userSize = Math.Max(finalSize - allPreferredArrangeSize, 0.0) * (starValue / tempDefinitions[i].SizeCache); resolvedSize = Math.Min(userSize, tempDefinitions[i].UserMaxSize); resolvedSize = Math.Max(tempDefinitions[i].MinSizeForArrange, resolvedSize); } tempDefinitions[i].SizeCache = resolvedSize; allPreferredArrangeSize += resolvedSize; } while (++i < starDefinitionsCount); } if ( allPreferredArrangeSize > finalSize && !_AreClose(allPreferredArrangeSize, finalSize) ) { Array.Sort(tempDefinitions, 0, definitions.Length, s_distributionOrderComparer); double sizeToDistribute = finalSize - allPreferredArrangeSize; for (int i = 0; i < definitions.Length; ++i) { double final = tempDefinitions[i].SizeCache + (sizeToDistribute / (definitions.Length - i)); final = Math.Max(final, tempDefinitions[i].MinSizeForArrange); final = Math.Min(final, tempDefinitions[i].SizeCache); sizeToDistribute -= (final - tempDefinitions[i].SizeCache); tempDefinitions[i].SizeCache = final; } } 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; } } ////// 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 [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeColumnDefinitions() { ExtendedData extData = ExtData; return ( extData != null && extData.ColumnDefinitions != null && extData.ColumnDefinitions.Count > 0 ); } ///true if ColumnDefinitions collection is not empty ////// Returns [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeRowDefinitions() { ExtendedData extData = ExtData; return ( extData != null && extData.RowDefinitions != null && extData.RowDefinitions.Count > 0 ); } ///true if RowDefinitions collection is not empty ////// 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 private bool CheckFlagsAnd(Flags flags) { return ((_flags & flags) == flags); } ///true if all the flags in the /// given bitmask are set on the object. ////// 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 /// private bool CheckFlagsOr(Flags flags) { return (flags == 0 || (_flags & flags) != 0); } ///true . ////// 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); } #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); } } ////// 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 /// Value to check. ///d == 0 . ///private static bool _IsZero(double d) { return (Math.Abs(d) < c_epsilon); } /// true if d == 0./// fp version of /// First value to compare /// Second value to compare ///d1 == d2 ///private static bool _AreClose(double d1, double d2) { return (Math.Abs(d1 - d2) < c_epsilon); } /// true if d1 == d2/// 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; #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 public static readonly DependencyProperty ShowGridLinesProperty = DependencyProperty.Register( "ShowGridLines", typeof(bool), typeof(Grid), new FrameworkPropertyMetadata( false, new PropertyChangedCallback(OnShowGridLinesPropertyChanged))); ///true grid lines are drawn to visualize location /// of grid lines. ////// 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. /// ////// [CommonDependencyProperty] public static readonly DependencyProperty ColumnProperty = DependencyProperty.RegisterAttached( "Column", typeof(int), typeof(Grid), new FrameworkPropertyMetadata( 0, new PropertyChangedCallback(OnCellAttachedPropertyChanged)), new ValidateValueCallback(IsIntValueNotNegative)); ///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 ./// 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. /// [CommonDependencyProperty] public static readonly DependencyProperty RowProperty = DependencyProperty.RegisterAttached( "Row", typeof(int), typeof(Grid), new FrameworkPropertyMetadata( 0, new PropertyChangedCallback(OnCellAttachedPropertyChanged)), new ValidateValueCallback(IsIntValueNotNegative)); ////// ///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 ./// 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 [CommonDependencyProperty] public static readonly DependencyProperty ColumnSpanProperty = DependencyProperty.RegisterAttached( "ColumnSpan", typeof(int), typeof(Grid), new FrameworkPropertyMetadata( 1, new PropertyChangedCallback(OnCellAttachedPropertyChanged)), new ValidateValueCallback(IsIntValueGreaterThanZero)); ///1 . ////// 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 [CommonDependencyProperty] public static readonly DependencyProperty RowSpanProperty = DependencyProperty.RegisterAttached( "RowSpan", typeof(int), typeof(Grid), new FrameworkPropertyMetadata( 1, new PropertyChangedCallback(OnCellAttachedPropertyChanged)), new ValidateValueCallback(IsIntValueGreaterThanZero)); ///1 . ////// 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 internal bool U { get { return (_u); } } private int _start; private int _count; private bool _u; } ///true if this is a column span. ///false if this is a row span. ////// SpanPreferredDistributionOrderComparer. /// private class SpanPreferredDistributionOrderComparer : IComparer { public int Compare(object x, object y) { if (x == y) return (0); DefinitionBase definitionX = (DefinitionBase)x; DefinitionBase definitionY = (DefinitionBase)y; if (definitionX.UserSize.IsAuto) { if (definitionY.UserSize.IsAuto) return ((definitionX.MinSize > definitionY.MinSize) ? 1 : -1); return (-1); } else { if (!definitionY.UserSize.IsAuto) return ((definitionX.PreferredSize > definitionY.PreferredSize) ? 1 : -1); return (1); } } } ////// SpanMaxDistributionOrderComparer. /// private class SpanMaxDistributionOrderComparer : IComparer { public int Compare(object x, object y) { if (x == y) return (0); DefinitionBase definitionX = (DefinitionBase)x; DefinitionBase definitionY = (DefinitionBase)y; if (definitionX.UserSize.IsAuto) { if (definitionY.UserSize.IsAuto) return ((definitionX.SizeCache > definitionY.SizeCache) ? 1 : -1); return (1); } else { if (!definitionY.UserSize.IsAuto) return ((definitionX.SizeCache > definitionY.SizeCache) ? 1 : -1); return (-1); } } } ////// StarDistributionOrderComparer. /// private class StarDistributionOrderComparer : IComparer { public int Compare(object x, object y) { if (x == y) return (0); DefinitionBase definitionX = (DefinitionBase)x; DefinitionBase definitionY = (DefinitionBase)y; return ((definitionX.SizeCache > definitionY.SizeCache) ? 1 : -1); } } ////// DistributionOrderComparer. /// private class DistributionOrderComparer: IComparer { public int Compare(object x, object y) { if (x == y) return (0); DefinitionBase definitionX = (DefinitionBase)x; DefinitionBase definitionY = (DefinitionBase)y; return ((definitionX.SizeCache - definitionX.MinSizeForArrange) > (definitionY.SizeCache - definitionY.MinSizeForArrange) ? 1 : -1); } } ////// 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
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DataGridViewAutoSizeModeEventArgs.cs
- ConfigsHelper.cs
- DbTransaction.cs
- UInt64Converter.cs
- Header.cs
- ValueType.cs
- CookieProtection.cs
- _HeaderInfo.cs
- ResourceExpression.cs
- FlowLayoutPanel.cs
- TypeDescriptor.cs
- EnumMemberAttribute.cs
- AsymmetricSignatureFormatter.cs
- Constants.cs
- RuntimeArgumentHandle.cs
- BrowserDefinition.cs
- Viewport3DAutomationPeer.cs
- HMACSHA1.cs
- DisplayInformation.cs
- FontSourceCollection.cs
- EntityCommandExecutionException.cs
- PolygonHotSpot.cs
- TypedReference.cs
- HtmlTableCell.cs
- _emptywebproxy.cs
- StopRoutingHandler.cs
- storepermission.cs
- ConsumerConnectionPoint.cs
- TransformerInfoCollection.cs
- HtmlInputHidden.cs
- XmlObjectSerializerReadContextComplex.cs
- QueryOutputWriter.cs
- CqlLexer.cs
- Token.cs
- EnumerableRowCollection.cs
- PublisherMembershipCondition.cs
- UIElement3D.cs
- FilteredAttributeCollection.cs
- Storyboard.cs
- GeometryHitTestResult.cs
- TextSchema.cs
- SrgsElement.cs
- DoubleCollection.cs
- NextPreviousPagerField.cs
- WebPartZone.cs
- TypeGeneratedEventArgs.cs
- _NetRes.cs
- TypeSchema.cs
- TableLayout.cs
- Parser.cs
- SqlStream.cs
- ExtensionSimplifierMarkupObject.cs
- WindowsStreamSecurityBindingElement.cs
- PeerNearMe.cs
- TrackingRecord.cs
- SingleSelectRootGridEntry.cs
- SrgsElementFactoryCompiler.cs
- ChannelSettingsElement.cs
- ProcessHostMapPath.cs
- SafeWaitHandle.cs
- ExternalFile.cs
- ObjectParameter.cs
- Assembly.cs
- DatePicker.cs
- CustomValidator.cs
- SuppressIldasmAttribute.cs
- Propagator.cs
- RenderingBiasValidation.cs
- CodeExporter.cs
- IdleTimeoutMonitor.cs
- ToolStripPanel.cs
- ControlCollection.cs
- MetaModel.cs
- RuntimeIdentifierPropertyAttribute.cs
- CredentialCache.cs
- TextStore.cs
- RightNameExpirationInfoPair.cs
- NetworkInformationException.cs
- RecordsAffectedEventArgs.cs
- PropertyGridCommands.cs
- CalculatedColumn.cs
- RestClientProxyHandler.cs
- SuppressMergeCheckAttribute.cs
- DtdParser.cs
- WebEventTraceProvider.cs
- Grid.cs
- RegexCompilationInfo.cs
- PassportAuthentication.cs
- ErrorFormatterPage.cs
- StringCollection.cs
- Nullable.cs
- KeyValueConfigurationCollection.cs
- ValuePattern.cs
- ElementAction.cs
- SqlDependencyListener.cs
- OlePropertyStructs.cs
- ExternalException.cs
- Matrix.cs
- datacache.cs
- PrintingPermissionAttribute.cs