Размещение элементов в контроле Grid может быть утомительным. Удобнее, когда они автоматом размещаются по ячейкам, как в UniformGrid.
ColumnsGrid добавляет к этому следующие возможности:
- Колонки задаются одной строкой Columns=«Auto,*,200,Shared1»
- Задается интервал между колонками Spacing=«4»
- Переход на следующую строку задается элементом <Separator Height=«4»/>
using System;
using System.Windows;
using System.Windows.Controls;
public class ColumnsGrid : Grid {
public ColumnsGrid() : base() {
ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
}
Свойство Spacing
public double Spacing {
get { return (double)GetValue(SpacingProperty); }
set { SetValue(SpacingProperty, value); }
}
public static readonly DependencyProperty SpacingProperty =
DependencyProperty.Register("Spacing", typeof(double), typeof(ColumnsGrid),
new FrameworkPropertyMetadata(0.0, SpacingChangedCallback));
static void SpacingChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) {
((ColumnsGrid)d).SpacingChanged((double)e.NewValue);
}
void SpacingChanged(double value) {
bool even = true;
var l = new GridLength(Spacing);
foreach (var cd in ColumnDefinitions) {
if (!even) cd.Width = l;
even = !even;
}
}
Свойство Columns
public string Columns{
get { return (string)GetValue(ColumnsProperty); }
set { SetValue(ColumnsProperty, value); }
}
public static readonly DependencyProperty ColumnsProperty =
DependencyProperty.Register("Columns", typeof(string), typeof(ColumnsGrid),
new FrameworkPropertyMetadata("Auto", ColumnsChangedCallback));
static void ColumnsChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) {
((ColumnsGrid)d).ColumnsChanged((double)e.NewValue);
}
void ColumnsChanged(string value) {
var ss = value.Split(',');
ColumnDefinitions.Clear();
var cnv = new GridLengthConverter();
foreach (var s in ss) {
var cd = new ColumnDefinition();
try {
cd.Width = (GridLength)cnv.ConvertFromInvariantString(s.Trim());
} catch {
cd.Width = GridLength.Auto;
cd.SharedSizeGroup = s;
}
if (ColumnDefinitions.Count>0) ColumnDefinitions.Add(
new ColumnDefinition() { Width = new GridLength(Spacing) });
ColumnDefinitions.Add(cd);
}
if (ColumnDefinitions.Count==0) ColumnDefinitions.Add(
new ColumnDefinition() { Width = GridLength.Auto });
InvokeArrange();
}
protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved) {
base.OnVisualChildrenChanged(visualAdded, visualRemoved);
InvokeArrange();
}
bool ArrangeInvoked;
void InvokeArrange() {
if (ArrangeInvoked) return;
ArrangeInvoked = true;
Application.Current.Dispatcher.BeginInvoke(new Action(Arrange));
}
void Arrange() {
ArrangeInvoked = false;
RowDefinitions.Clear();
RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
int row = 0, col = 0;
foreach (UIElement child in InternalChildren) {
if (child is Separator) {
child.Visibility = Visibility.Hidden;
col = 0;
row++;
RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
SetColumn(child, 0);
SetRow(child, row);
row++;
RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
} else {
SetColumn(child, col);
SetRow(child, row);
col += 2;
}
}
}
}
Публикации на эту тему на Хабре:
Фишки XAML-разработчика: динамический Grid
Автор: Янтимиров Амир Афанасьевич