using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
namespace WpfBanner
{
/// <summary>
/// Adapted from: https://rachel53461.wordpress.com/2011/09/17/wpf-grids-rowcolumn-count-properties/
/// </summary>
public static class GridHelpers
{
#region RowCount Property
/// <summary>
/// Adds the specified number of Rows to RowDefinitions.
/// Default Height is Auto
/// </summary>
public static readonly DependencyProperty RowCountProperty =
DependencyProperty.RegisterAttached(
"RowCount", typeof(int), typeof(GridHelpers),
new PropertyMetadata(-1, RowCountChanged));
public static int GetRowCount(DependencyObject obj)
=> (int)obj.GetValue(RowCountProperty);
public static void SetRowCount(DependencyObject obj, int value)
=> obj.SetValue(RowCountProperty, value);
public static void RowCountChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if (!(obj is Grid grid) || (int)e.NewValue < 0)
return;
grid.RowDefinitions.Clear();
for (int i = 0; i < (int)e.NewValue; i++)
grid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
SetStarRows(grid);
RegisterForLayoutUpdate(grid);
}
#endregion
#region ColumnCount Property
/// <summary>
/// Adds the specified number of Columns to ColumnDefinitions.
/// Default Width is Auto
/// </summary>
public static readonly DependencyProperty ColumnCountProperty =
DependencyProperty.RegisterAttached(
"ColumnCount", typeof(int), typeof(GridHelpers),
new PropertyMetadata(-1, ColumnCountChanged));
public static int GetColumnCount(DependencyObject obj)
=> (int)obj.GetValue(ColumnCountProperty);
public static void SetColumnCount(DependencyObject obj, int value)
=> obj.SetValue(ColumnCountProperty, value);
public static void ColumnCountChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if (!(obj is Grid grid) || (int)e.NewValue < 0)
return;
grid.ColumnDefinitions.Clear();
for (int i = 0; i < (int)e.NewValue; i++)
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
SetStarColumns(grid);
RegisterForLayoutUpdate(grid);
}
#endregion
#region StarRows Property
/// <summary>
/// Makes the specified Row's Height equal to Star.
/// Can set on multiple Rows
/// </summary>
public static readonly DependencyProperty StarRowsProperty =
DependencyProperty.RegisterAttached(
"StarRows", typeof(string), typeof(GridHelpers),
new PropertyMetadata(string.Empty, StarRowsChanged));
public static string GetStarRows(DependencyObject obj)
=> (string)obj.GetValue(StarRowsProperty);
public static void SetStarRows(DependencyObject obj, string value)
=> obj.SetValue(StarRowsProperty, value);
public static void StarRowsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if (!(obj is Grid grid) || string.IsNullOrEmpty(e.NewValue.ToString()))
return;
SetStarRows(grid);
RegisterForLayoutUpdate(grid);
}
#endregion
#region StarColumns Property
/// <summary>
/// Makes the specified Column's Width equal to Star.
/// Can set on multiple Columns
/// </summary>
public static readonly DependencyProperty StarColumnsProperty =
DependencyProperty.RegisterAttached(
"StarColumns", typeof(string), typeof(GridHelpers),
new PropertyMetadata(string.Empty, StarColumnsChanged));
public static string GetStarColumns(DependencyObject obj)
=> (string)obj.GetValue(StarColumnsProperty);
public static void SetStarColumns(DependencyObject obj, string value)
=> obj.SetValue(StarColumnsProperty, value);
public static void StarColumnsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if (!(obj is Grid grid) || string.IsNullOrEmpty(e.NewValue.ToString()))
return;
SetStarColumns(grid);
RegisterForLayoutUpdate(grid);
}
#endregion
static void SetStarColumns(Grid grid)
{
string[] starColumns = GetStarColumns(grid).Split(',');
for (int i = 0; i < grid.ColumnDefinitions.Count; i++)
{
if (starColumns.Contains(i.ToString()))
grid.ColumnDefinitions[i].Width = new GridLength(1, GridUnitType.Star);
}
}
static void SetStarRows(Grid grid)
{
string[] starRows = GetStarRows(grid).Split(',');
for (int i = 0; i < grid.RowDefinitions.Count; i++)
{
if (starRows.Contains(i.ToString()))
grid.RowDefinitions[i].Height = new GridLength(1, GridUnitType.Star);
}
}
static HashSet<Grid> _registered = new HashSet<Grid>();
static void RegisterForLayoutUpdate(Grid grid)
{
if (_registered.Contains(grid))
return;
_registered.Add(grid);
grid.LayoutUpdated += (o, e) =>
{
int columnCount = grid.ColumnDefinitions.Count;
int count = 0;
foreach (var presenter in grid.Children.OfType<ContentPresenter>())
{
Grid.SetColumn(presenter, count % columnCount);
Grid.SetRow(presenter, count / columnCount);
count++;
}
};
}
}
}