Skip to content

Instantly share code, notes, and snippets.

@Jeff-Walker
Created April 13, 2012 16:14
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jeff-Walker/2378017 to your computer and use it in GitHub Desktop.
Save Jeff-Walker/2378017 to your computer and use it in GitHub Desktop.
Enhanced SimpleGridLayout
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
namespace Wpf {
/*
* This code is made available with no warranty. It comes as-is, but discuss changes if you like.
* I consider this in the public domain.
*
* Stolen from Sam Naseri @ http://samondotnet.blogspot.com/2012/03/wpf-grid-layout-simplified-using-rows.html
*
* [from the article]
* This code adds these attached properties to Grid
*
* Grid.Rows
* Grid.Columns
*
* and adds these attached properties to UIElemnet
*
*
* Cell
*
* Grid.Rows and Grid.Columns are same thing but one is for specifying rows and one is for columns.
* These two properties are simply text value which you can set it according to the following Rules:
*
* Separate items with semi colon(;) , Example "auto;auto;*"
* Use auto for adding an Auto sized row or column , Example "auto;auto"
* Specify * for adding an star sized row or column, Example "1*;2*; *"
* Specify only a number for adding a fixed size row or column, Example "200;200;100"
* Append # followed by a number to add multiple rows and columns of same sizing. "1*#4;auto"
* The number of starts in an item will multiplies star factor. Example "**;***;*" instead of "2*;3*;*"
*
* XAML Sample:
*
*
* <Grid s:Grid.Rows="auto;1*;auto;auto" s:Grid.Columns="*#5;auto"> ... </Grid>
*
* [added by Jeff Walker]
*
* <Grid s:SimpleGridLayout.Columns="[_SharedSizeGroup1],[_SharedSizeGroup2],*"
* s:SimpleGridLayout.SharedSizeGroupPrefix="Prefix">...</Grid>
*
* This will produce a grid with three colums, the first is like:
* <ColumnDefinition Width="Auto" SharedSizeGroup="Prefix_SharedGroup1"/>
* <ColumnDefinition Width="Auto" SharedSizeGroup="Prefix_SharedGroup2"/>
* <ColumnDefinition Width="*" />
*
* The only senseble width setting for a SharedSizeGroup column is Auto, so that is forced on you.
* (Also, * doesn't work with a SharedSizeGroup)
*
*/
public static class SimpleGridLayout {
internal struct GridDefinitionInformation {
public GridLength GridLength;
public string SharedSizeGroup;
}
#region helper methods
internal static IEnumerable<GridDefinitionInformation> Parse(string text) {
if (text.Contains("#")) {
var parts = text.Split(new[] { '#' }, StringSplitOptions.RemoveEmptyEntries);
var count = int.Parse(parts[1].Trim());
return Enumerable.Repeat(ParseGridDefinition(parts[0]), count);
} else {
return new[] { ParseGridDefinition(text) };
}
}
internal static GridLength ParseGridLength(string text) {
text = text.Trim();
if (text.ToLower() == "auto")
return GridLength.Auto;
if (text.Contains("*")) {
var startCount = text.ToCharArray().Count(c => c == '*');
var pureNumber = text.Replace("*", "");
var ratio = string.IsNullOrWhiteSpace(pureNumber) ? 1 : double.Parse(pureNumber);
return new GridLength(startCount * ratio, GridUnitType.Star);
}
var pixelsCount = double.Parse(text);
return new GridLength(pixelsCount, GridUnitType.Pixel);
}
internal static GridDefinitionInformation ParseGridDefinition(string text) {
text = text.Trim();
var result = new GridDefinitionInformation();
if ( text.StartsWith("[") && text.EndsWith("]")) {
result.SharedSizeGroup = text.Substring(1, text.Length - 2); // inside the []s
result.GridLength = GridLength.Auto;
} else {
result.GridLength = ParseGridLength(text);
}
return result;
}
static string CalculateSharedSize(string sharedSizeGroup, string sharedSizeGroupPrefix) {
if (sharedSizeGroup != null && sharedSizeGroupPrefix != null) {
return sharedSizeGroupPrefix + sharedSizeGroup;
}
return sharedSizeGroup;
}
#endregion
#region GridColumnsLayout
public static string GetColumns(DependencyObject obj) {
return (string)obj.GetValue(ColumnsProperty);
}
public static void SetColumns(DependencyObject obj, string value) {
obj.SetValue(ColumnsProperty, value);
}
public static readonly DependencyProperty ColumnsProperty =
DependencyProperty.RegisterAttached("Columns", typeof(string), typeof(SimpleGridLayout),
new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure, Columns_PropertyChangedCallback));
static void Columns_PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) {
var grid = d as Grid;
var oldValue = e.OldValue as string;
var newValue = e.NewValue as string;
if (grid == null || oldValue == null || newValue == null)
return;
var prefix = GetSharedSizeGroupPrefix(grid);
if (oldValue != newValue) {
grid.ColumnDefinitions.Clear();
newValue
.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
.SelectMany(Parse)
.Select(gridDefInfo => new ColumnDefinition {
Width = gridDefInfo.GridLength,
SharedSizeGroup = CalculateSharedSize(gridDefInfo.SharedSizeGroup, prefix)
})
.ToList().ForEach(grid.ColumnDefinitions.Add);
}
}
#endregion
#region Rows
public static string GetRows(DependencyObject obj) {
return (string)obj.GetValue(RowsProperty);
}
public static void SetRows(DependencyObject obj, string value) {
obj.SetValue(RowsProperty, value);
}
public static readonly DependencyProperty RowsProperty =
DependencyProperty.RegisterAttached("Rows", typeof(string), typeof(SimpleGridLayout),
new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure, Rows_PropertyChangedCallback));
static void Rows_PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) {
var grid = d as Grid;
var oldValue = e.OldValue as string;
var newValue = e.NewValue as string;
if (grid == null || oldValue == null || newValue == null)
return;
var prefix = GetSharedSizeGroupPrefix(grid);
if (oldValue != newValue) {
grid.RowDefinitions.Clear();
newValue
.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
.SelectMany(Parse)
.Select(gridDefInfo => new RowDefinition {
Height = gridDefInfo.GridLength,
SharedSizeGroup = CalculateSharedSize(gridDefInfo.SharedSizeGroup, prefix)
})
.ToList().ForEach(grid.RowDefinitions.Add);
}
}
#endregion
#region Cell
public static string GetCell(DependencyObject obj) {
return (string)obj.GetValue(CellProperty);
}
public static void SetCell(DependencyObject obj, string value) {
obj.SetValue(CellProperty, value);
}
public static readonly DependencyProperty CellProperty =
DependencyProperty.RegisterAttached("Cell", typeof(string), typeof(SimpleGridLayout),
new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure, Cell_PropertyChangedCallback));
static void Cell_PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) {
var element = d as UIElement;
var oldValue = e.OldValue as string;
var newValue = e.NewValue as string;
if (element == null || oldValue == null || newValue == null)
return;
if (oldValue != newValue) {
var rowAndColumn = newValue.Split(new[] { ' ', ';' });
// only set row and/or column if they are specified
// "1" or "1;" for only row, ";1" for column only
if ( !string.IsNullOrEmpty(rowAndColumn[0])) {
var row = int.Parse(rowAndColumn[0]);
Grid.SetRow(element, row);
}
if (!string.IsNullOrEmpty(rowAndColumn[1])) {
var column = int.Parse(rowAndColumn[1]);
Grid.SetColumn(element, column);
}
}
}
#endregion
#region SharedSizeGroupPrefix
public static string GetSharedSizeGroupPrefix(DependencyObject obj) {
return (string)obj.GetValue(SharedSizeGroupPrefixProperty);
}
public static void SetSharedSizeGroupPrefix(DependencyObject obj, string value) {
obj.SetValue(SharedSizeGroupPrefixProperty, value);
}
public static readonly DependencyProperty SharedSizeGroupPrefixProperty =
DependencyProperty.RegisterAttached("SharedSizeGroupPrefix", typeof(string), typeof(SimpleGridLayout), new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure));
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment