Created
April 13, 2012 16:14
-
-
Save Jeff-Walker/2378017 to your computer and use it in GitHub Desktop.
Enhanced SimpleGridLayout
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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