Размещение элементов в контроле Grid может быть утомительным. Удобнее, когда они автоматом размещаются по ячейкам, как в UniformGrid.
ColumnsGrid добавляет к этому следующие возможности:
Публикации на эту тему на Хабре:
> Фишки XAML-разработчика: динамический Grid
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
Комментарии (6)
geekmetwice
26.08.2017 20:04+4Отвратительная подача материала! Какой-то ColumnsGrid… он что, размещает контролы в колонки, а не по строкам? Пара фич + никчемушные листинги, зато ни строчки XAML-кода! Кто и как может извлечь пользу из вашего… гм… даже не опуса, а какого-то «текстового выкрика»?
AmirYantimirov Автор
27.08.2017 08:42Пожалуйста:
<local:ColumnsGrid Columns="Header,*" Spacing="4" > <RadioButton Name="radioFontDefault" Content="Default font" /> <TextBox Name="textFontDefault" Text="Segoe UI" IsReadOnly="True"/> <Separator Height="4" /> <RadioButton Name="radioFontCustom" Content="Custom font" /> <TextBox Name="textFontCustom" Text="Segoe UI" IsReadOnly="True"/> </local:ColumnsGrid>
lexxpavlov
26.08.2017 23:41Только вчера сделал такой же грид, с тем же названием. Только я отнаследовал от Panel, а не Grid (как и UniformGrid). У меня ещё есть RowSpacing, помимо ColumnSpacing.
Nikita_Danilov
Надежный и точный Layout и так очень мощная сторона WPF, за это он мне полюбился в своё время.
Но, к сожалению, за все эти годы так и не подвезли возможность устанавливать несколько стилей для одного элемента, приходится плодить мелкие подстили на каждый случай, из-за чего становится невыносимой поддержка больших библиотек стилей.
kekekeks
А вот в Авалонии эту проблему устранили.