ColumnsGrid для WPF

в 5:55, , рубрики: .net, C#, custom grid, wpf, Программирование, разработка под windows

Размещение элементов в контроле Grid может быть утомительным. Удобнее, когда они автоматом размещаются по ячейкам, как в UniformGrid.

ColumnsGrid добавляет к этому следующие возможности:

  1. Колонки задаются одной строкой Columns=«Auto,*,200,Shared1»
  2. Задается интервал между колонками Spacing=«4»
  3. Переход на следующую строку задается элементом <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

Автор: Янтимиров Амир Афанасьевич

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js