How about using attached properties and syntax like this:
<!-- Define xmlns:b="clr-namespace:Behaviors" --><!-- Create 5 columns: 1/3 width, 2/3 width, auto, auto and 50 pixels --><Grid b:GridBehavior.Columns="1*,2*,,auto,50"> ... </Grid>
Implementation:
using System.ComponentModel;using System.Windows;using System.Windows.Controls;namespace Behaviors;public class GridBehavior : DependencyObject{ public static readonly DependencyProperty ColumnsProperty = DependencyProperty.RegisterAttached("Columns", typeof(string), typeof(GridBehavior), new PropertyMetadata((s, e) => { if (s is not Grid grid) throw new InvalidOperationException("Must be Grid."); var converter = TypeDescriptor.GetConverter(typeof(GridLength)); var columns = e.NewValue.ToString()!.Split(",").Select(o => { if (o == "") return new ColumnDefinition(); else if (converter.ConvertFromString(o) is GridLength gridLength) return new ColumnDefinition { Width = gridLength }; return new ColumnDefinition(); }); grid.ColumnDefinitions.Clear(); foreach (var column in columns) grid.ColumnDefinitions.Add(column); })); public static string GetColumns(DependencyObject obj) => (string)obj.GetValue(ColumnsProperty); public static void SetColumns(DependencyObject obj, string value) => obj.SetValue(ColumnsProperty, value);}
You can omit verbose xaml to define columns in many cases.
In your specific case the value will be
b:GridBehavior.Columns=",,,,,,,,,,,,,,,,,,,,,,,"
which isn't bad, right?
TODO: multiplier for repeated columns, support GroupName
(as suffix #SomeGroupName
?), do same for rows.