protected override Size ArrangeOverride(Size finalSize) { bool has_row_definitions = row_definitions.Count != 0; bool has_column_definitions = column_definitions.Count != 0; if ((has_row_definitions || has_column_definitions) && !measure_called) { throw new NullReferenceException(); } int row_count = GetRowColumnCount(row_definitions.Count); int column_count = GetRowColumnCount(column_definitions.Count); double [] row_heights = new double [row_count]; double [] column_widths = new double [column_count]; int index; #region Compute initial row and column size if (has_row_definitions) { for (index = 0; index < row_count; index++) { GridLength row_definition_height = row_definitions [index].Height; row_heights [index] = row_definition_height.IsAbsolute ? row_definition_height.Value : double.PositiveInfinity; } } else { row_heights [0] = finalSize.Height; } if (has_column_definitions) { for (index = 0; index < column_count; index++) { GridLength column_definition_width = column_definitions [index].Width; column_widths [index] = column_definition_width.IsAbsolute ? column_definition_width.Value : double.PositiveInfinity; } } else { column_widths [0] = finalSize.Width; } #endregion if (has_row_definitions || has_column_definitions) { double [] desired_row_heights = new double [row_count]; double [] desired_column_widths = new double [column_count]; foreach (UIElement child in InternalChildren) { if (has_row_definitions) { int child_row = Math.Min(GetRow(child), row_count - 1); if (!row_definitions [child_row].Height.IsAbsolute && GetRowSpan(child) == 1) { desired_row_heights [child_row] = Math.Max(desired_row_heights [child_row], child.DesiredSize.Height); } } if (has_column_definitions) { int child_column = Math.Min(GetColumn(child), column_count - 1); if (!column_definitions [child_column].Width.IsAbsolute && GetColumnSpan(child) == 1) { desired_column_widths [child_column] = Math.Max(desired_column_widths [child_column], child.DesiredSize.Width); } } } if (has_row_definitions) { for (index = 0; index < row_count; index++) { if (row_definitions [index].Height.IsAuto) { row_heights [index] = desired_row_heights [index]; } } } if (has_column_definitions) { for (index = 0; index < column_count; index++) { if (column_definitions [index].Width.IsAuto) { column_widths [index] = desired_column_widths [index]; } } } #region Apply definition minimum and maximum if (has_row_definitions) { for (index = 0; index < row_count; index++) { RowDefinition row_definition = row_definitions [index]; row_heights [index] = AdjustToBeInRange(row_heights [index], row_definition.MinHeight, row_definition.MaxHeight); } } if (has_column_definitions) { for (index = 0; index < column_count; index++) { ColumnDefinition column_definition = column_definitions [index]; column_widths [index] = AdjustToBeInRange(column_widths [index], column_definition.MinWidth, column_definition.MaxWidth); } } #endregion #region Distribute remaining space to rows/columns with star size double total_star; double remaining_lenght; double star_ratio; bool [] uses_star_sizing; bool current_star_sizing_valid; if (has_row_definitions) { uses_star_sizing = new bool [row_count]; for (index = 0; index < row_count; index++) { uses_star_sizing [index] = row_definitions [index].Height.IsStar; } do { current_star_sizing_valid = true; total_star = 0; remaining_lenght = finalSize.Height; for (index = 0; index < row_count; index++) { if (uses_star_sizing [index]) { total_star += row_definitions [index].Height.Value; } else { remaining_lenght -= row_heights [index]; } } if (remaining_lenght > 0 && total_star != 0) { star_ratio = remaining_lenght / total_star; for (index = 0; index < row_count; index++) { if (uses_star_sizing [index]) { RowDefinition definition = row_definitions [index]; double proposed_lenght = Math.Max(definition.Height.Value * star_ratio, desired_row_heights [index]); if (proposed_lenght < definition.MinHeight) { row_heights [index] = definition.MinHeight; uses_star_sizing [index] = false; current_star_sizing_valid = false; break; } else if (proposed_lenght > definition.MaxHeight) { row_heights [index] = definition.MaxHeight; uses_star_sizing [index] = false; current_star_sizing_valid = false; break; } else { row_heights [index] = proposed_lenght; } } } } } while (!current_star_sizing_valid); } if (has_column_definitions) { uses_star_sizing = new bool [column_count]; for (index = 0; index < column_count; index++) { uses_star_sizing [index] = column_definitions [index].Width.IsStar; } do { current_star_sizing_valid = true; total_star = 0; remaining_lenght = finalSize.Width; for (index = 0; index < column_count; index++) { if (uses_star_sizing [index]) { total_star += column_definitions [index].Width.Value; } else { remaining_lenght -= column_widths [index]; } } if (remaining_lenght > 0 && total_star != 0) { star_ratio = remaining_lenght / total_star; for (index = 0; index < column_count; index++) { if (uses_star_sizing [index]) { ColumnDefinition definition = column_definitions [index]; double proposed_lenght = Math.Max(definition.Width.Value * star_ratio, desired_column_widths [index]); if (proposed_lenght < definition.MinWidth) { column_widths [index] = definition.MinWidth; uses_star_sizing [index] = false; current_star_sizing_valid = false; break; } else if (proposed_lenght > definition.MaxWidth) { column_widths [index] = definition.MaxWidth; uses_star_sizing [index] = false; current_star_sizing_valid = false; break; } else { column_widths [index] = proposed_lenght; } } } } } while (!current_star_sizing_valid); } #endregion #region Set row/column definitions ActualWidth/Height and Offset values double offset; if (has_row_definitions) { remaining_lenght = finalSize.Height; offset = 0; for (index = 0; index < row_count; index++) { if (row_heights [index] > remaining_lenght) { row_heights [index] = remaining_lenght; } remaining_lenght -= row_heights [index]; RowDefinition definition = row_definitions [index]; definition.Offset = offset; offset += definition.ActualHeight = row_heights [index]; } } if (has_column_definitions) { remaining_lenght = finalSize.Width; offset = 0; for (index = 0; index < column_count; index++) { if (column_widths [index] > remaining_lenght) { column_widths [index] = remaining_lenght; } remaining_lenght -= column_widths [index]; ColumnDefinition definition = column_definitions [index]; definition.Offset = offset; offset += definition.ActualWidth = column_widths [index]; } } #endregion } #region Arrange children foreach (UIElement child in InternalChildren) { Rect rect = new Rect(); int row_column = Math.Min(GetRow(child), row_count - 1); for (index = 0; index < row_column; index++) { rect.Y += row_heights [index]; } int maximum = Math.Min(row_column + GetRowSpan(child), row_count); for (index = row_column; index < maximum; index++) { rect.Height += row_heights [index]; } row_column = Math.Min(GetColumn(child), column_count - 1); for (index = 0; index < row_column; index++) { rect.X += column_widths [index]; } maximum = Math.Min(row_column + GetColumnSpan(child), column_count); for (index = row_column; index < maximum; index++) { rect.Width += column_widths [index]; } child.Arrange(rect); } #endregion #region Create or update GridLinesRenderer if (grid_lines_renderer == null) { if (ShowGridLines && (has_row_definitions || has_column_definitions)) { grid_lines_renderer = new GridLinesRenderer(this); AddVisualChild(grid_lines_renderer); grid_lines_renderer.Rebuild(); } } else { grid_lines_renderer.Rebuild(); } #endregion return(finalSize); }
/// <summary> /// 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. /// </summary> 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); }
protected override Size ArrangeOverride (Size finalSize) { bool has_row_definitions = row_definitions.Count != 0; bool has_column_definitions = column_definitions.Count != 0; if ((has_row_definitions || has_column_definitions) && !measure_called) throw new NullReferenceException (); int row_count = GetRowColumnCount (row_definitions.Count); int column_count = GetRowColumnCount (column_definitions.Count); double [] row_heights = new double [row_count]; double [] column_widths = new double [column_count]; int index; #region Compute initial row and column size if (has_row_definitions) for (index = 0; index < row_count; index++) { GridLength row_definition_height = row_definitions [index].Height; row_heights [index] = row_definition_height.IsAbsolute ? row_definition_height.Value : double.PositiveInfinity; } else row_heights [0] = finalSize.Height; if (has_column_definitions) for (index = 0; index < column_count; index++) { GridLength column_definition_width = column_definitions [index].Width; column_widths [index] = column_definition_width.IsAbsolute ? column_definition_width.Value : double.PositiveInfinity; } else column_widths [0] = finalSize.Width; #endregion if (has_row_definitions || has_column_definitions) { double [] desired_row_heights = new double [row_count]; double [] desired_column_widths = new double [column_count]; foreach (UIElement child in InternalChildren) { if (has_row_definitions) { int child_row = Math.Min (GetRow (child), row_count - 1); if (!row_definitions [child_row].Height.IsAbsolute && GetRowSpan (child) == 1) desired_row_heights [child_row] = Math.Max (desired_row_heights [child_row], child.DesiredSize.Height); } if (has_column_definitions) { int child_column = Math.Min (GetColumn (child), column_count - 1); if (!column_definitions [child_column].Width.IsAbsolute && GetColumnSpan (child) == 1) desired_column_widths [child_column] = Math.Max (desired_column_widths [child_column], child.DesiredSize.Width); } } if (has_row_definitions) for (index = 0; index < row_count; index++) if (row_definitions [index].Height.IsAuto) row_heights [index] = desired_row_heights [index]; if (has_column_definitions) for (index = 0; index < column_count; index++) if (column_definitions [index].Width.IsAuto) column_widths [index] = desired_column_widths [index]; #region Apply definition minimum and maximum if (has_row_definitions) for (index = 0; index < row_count; index++) { RowDefinition row_definition = row_definitions [index]; row_heights [index] = AdjustToBeInRange (row_heights [index], row_definition.MinHeight, row_definition.MaxHeight); } if (has_column_definitions) for (index = 0; index < column_count; index++) { ColumnDefinition column_definition = column_definitions [index]; column_widths [index] = AdjustToBeInRange (column_widths [index], column_definition.MinWidth, column_definition.MaxWidth); } #endregion #region Distribute remaining space to rows/columns with star size double total_star; double remaining_lenght; double star_ratio; bool [] uses_star_sizing; bool current_star_sizing_valid; if (has_row_definitions) { uses_star_sizing = new bool [row_count]; for (index = 0; index < row_count; index++) uses_star_sizing [index] = row_definitions [index].Height.IsStar; do { current_star_sizing_valid = true; total_star = 0; remaining_lenght = finalSize.Height; for (index = 0; index < row_count; index++) { if (uses_star_sizing [index]) total_star += row_definitions [index].Height.Value; else remaining_lenght -= row_heights [index]; } if (remaining_lenght > 0 && total_star != 0) { star_ratio = remaining_lenght / total_star; for (index = 0; index < row_count; index++) if (uses_star_sizing [index]) { RowDefinition definition = row_definitions [index]; double proposed_lenght = Math.Max (definition.Height.Value * star_ratio, desired_row_heights [index]); if (proposed_lenght < definition.MinHeight) { row_heights [index] = definition.MinHeight; uses_star_sizing [index] = false; current_star_sizing_valid = false; break; } else if (proposed_lenght > definition.MaxHeight) { row_heights [index] = definition.MaxHeight; uses_star_sizing [index] = false; current_star_sizing_valid = false; break; } else row_heights [index] = proposed_lenght; } } } while (!current_star_sizing_valid); } if (has_column_definitions) { uses_star_sizing = new bool [column_count]; for (index = 0; index < column_count; index++) uses_star_sizing [index] = column_definitions [index].Width.IsStar; do { current_star_sizing_valid = true; total_star = 0; remaining_lenght = finalSize.Width; for (index = 0; index < column_count; index++) { if (uses_star_sizing [index]) total_star += column_definitions [index].Width.Value; else remaining_lenght -= column_widths [index]; } if (remaining_lenght > 0 && total_star != 0) { star_ratio = remaining_lenght / total_star; for (index = 0; index < column_count; index++) if (uses_star_sizing [index]) { ColumnDefinition definition = column_definitions [index]; double proposed_lenght = Math.Max (definition.Width.Value * star_ratio, desired_column_widths [index]); if (proposed_lenght < definition.MinWidth) { column_widths [index] = definition.MinWidth; uses_star_sizing [index] = false; current_star_sizing_valid = false; break; } else if (proposed_lenght > definition.MaxWidth) { column_widths [index] = definition.MaxWidth; uses_star_sizing [index] = false; current_star_sizing_valid = false; break; } else column_widths [index] = proposed_lenght; } } } while (!current_star_sizing_valid); } #endregion #region Set row/column definitions ActualWidth/Height and Offset values double offset; if (has_row_definitions) { remaining_lenght = finalSize.Height; offset = 0; for (index = 0; index < row_count; index++) { if (row_heights [index] > remaining_lenght) row_heights [index] = remaining_lenght; remaining_lenght -= row_heights [index]; RowDefinition definition = row_definitions [index]; definition.Offset = offset; offset += definition.ActualHeight = row_heights [index]; } } if (has_column_definitions) { remaining_lenght = finalSize.Width; offset = 0; for (index = 0; index < column_count; index++) { if (column_widths [index] > remaining_lenght) column_widths [index] = remaining_lenght; remaining_lenght -= column_widths [index]; ColumnDefinition definition = column_definitions [index]; definition.Offset = offset; offset += definition.ActualWidth = column_widths [index]; } } #endregion } #region Arrange children foreach (UIElement child in InternalChildren) { Rect rect = new Rect (); int row_column = Math.Min (GetRow (child), row_count - 1); for (index = 0; index < row_column; index++) rect.Y += row_heights [index]; int maximum = Math.Min (row_column + GetRowSpan (child), row_count); for (index = row_column; index < maximum; index++) rect.Height += row_heights [index]; row_column = Math.Min (GetColumn (child), column_count - 1); for (index = 0; index < row_column; index++) rect.X += column_widths [index]; maximum = Math.Min (row_column + GetColumnSpan (child), column_count); for (index = row_column; index < maximum; index++) rect.Width += column_widths [index]; child.Arrange (rect); } #endregion #region Create or update GridLinesRenderer if (grid_lines_renderer == null) { if (ShowGridLines && (has_row_definitions || has_column_definitions)) { grid_lines_renderer = new GridLinesRenderer (this); AddVisualChild (grid_lines_renderer); grid_lines_renderer.Rebuild (); } } else grid_lines_renderer.Rebuild (); #endregion return finalSize; }