Zum Inhalt
Kuonen.UI

DataGrid-Ausbau

Was das DataGrid über das Raster hinaus kann: Zeilenköpfe mit Nummern, eine eingefrorene erste Spalte, Details unter der gewählten Zeile, Gruppen mit Köpfen zum Auf- und Zuklappen und eine Spalte mit Verweisen. Gewählte Zeilen lassen sich in das Feld darunter ziehen.

Vorführung: DataGrid-AusbauVorführung: DataGrid-Ausbau

KXAML

DataGridAusbauSeite.kxaml
<StackPanel xmlns="https://ui.kuonen.org/kxaml"
            xmlns:x="https://ui.kuonen.org/kxaml/x"
            xmlns:local="using:Kuonen.UI.Galerie.Seiten"
            x:Class="Kuonen.UI.Galerie.Seiten.DataGridAusbauVorfuehrung"
            Spacing="12">
  <CheckBox Content="Nach Ort gruppieren" Checked="Gruppen_Checked" Unchecked="Gruppen_Unchecked" />
  <!-- Zeilenköpfe mit Nummern, eingefrorene erste Spalte, Details unter der gewählten Zeile, Zeilen ziehen. -->
  <DataGrid x:Name="Gitter" Width="560" Height="240" HeadersVisibility="All" ShowRowNumbers="True" FrozenColumnCount="1" CanUserDragRows="True">
    <DataGrid.RowDetailsTemplate>
      <DataTemplate x:DataType="local:Projekt">
        <TextBlock Text="{Binding Notiz}" Margin="8,2,8,6" />
      </DataTemplate>
    </DataGrid.RowDetailsTemplate>
    <DataGridTextColumn x:DataType="local:Projekt" Header="Name" Width="120" Binding="{Binding Name, Mode=OneWay}" />
    <DataGridTextColumn x:DataType="local:Projekt" Header="Leitung" Width="120" Binding="{Binding Leitung, Mode=OneWay}" />
    <DataGridTextColumn x:Name="OrtSpalte" x:DataType="local:Projekt" Header="Ort" Width="100" Binding="{Binding Ort, Mode=OneWay}" />
    <DataGridHyperlinkColumn x:DataType="local:Projekt" Header="Web" Width="240" Binding="{Binding Web, Mode=OneWay}" />
  </DataGrid>
  <!-- Ein Ziel für gezogene Zeilen: es nimmt den Text (TSV) an. -->
  <Border Height="60" Width="560" AllowDrop="True" Background="#F0F4FA" DragOver="Ziel_DragOver" Drop="Ziel_Drop">
    <TextBlock x:Name="Abgelegt" Text="Gewählte Zeilen hierher ziehen." />
  </Border>
</StackPanel>
DataGridAusbauSeite.kxaml.cs
using Kuonen.UI;
using Kuonen.UI.Controls;
using Kuonen.UI.Eingabe;
using Kuonen.UI.Ereignisse;

namespace Kuonen.UI.Galerie.Seiten;

public sealed partial class DataGridAusbauSeite
{
    protected override Func<UIElement>? KxamlFabrik => () => new DataGridAusbauVorfuehrung();
}

/// <summary>KXAML-Fassung der Seite „DataGrid-Ausbau“: der Baum steht in DataGridAusbauSeite.kxaml, hier die Daten und das Verhalten.</summary>
public sealed partial class DataGridAusbauVorfuehrung
{
    public DataGridAusbauVorfuehrung()
    {
        InitializeComponent();
        string[] orte = ["Bern", "Basel", "Luzern", "Chur"];
        var projekte = new Projekt[200];
        for (int i = 0; i < projekte.Length; i++)
            projekte[i] = new Projekt($"Projekt {i + 1}", $"Leitung {(i % 7) + 1}", orte[i % 4], $"https://kuonen.org/projekt/{i + 1}", $"Notiz zu Projekt {i + 1}: im Plan.");
        Gitter.ItemsSource = projekte;
    }

    private void Gruppen_Checked(object sender, RoutedEventArgs e) => Gitter.GroupColumns.Add(OrtSpalte);

    private void Gruppen_Unchecked(object sender, RoutedEventArgs e) => Gitter.GroupColumns.Clear();

    private void Ziel_DragOver(object sender, DragEventArgs e) => e.Effects = e.Data.GetText() is null ? DragDropEffects.None : DragDropEffects.Copy;

    private void Ziel_Drop(object sender, DragEventArgs e) => Abgelegt.Text = e.Data.GetText() ?? "";
}

C#

DataGridAusbauSeite.cs
using Kuonen.UI;
using Kuonen.UI.Bindung;
using Kuonen.UI.Controls;
using Kuonen.UI.Eingabe;
using Kuonen.UI.Layout;
using Kuonen.UI.Media;

namespace Kuonen.UI.Galerie.Seiten;

/// <summary>Galerie-Seite: Zeilenköpfe, eingefrorene Spalte, Zeilendetails, Gruppen, Verweisspalte und Zeilen ziehen im <see cref="DataGrid"/>.</summary>
public sealed partial class DataGridAusbauSeite : GalerieSeite
{
    public override string Titel => "DataGrid-Ausbau";

    public override string Beschreibung =>
        "Was das DataGrid über das Raster hinaus kann: Zeilenköpfe mit Nummern, eine eingefrorene erste Spalte, Details unter der gewählten Zeile, "
        + "Gruppen mit Köpfen zum Auf- und Zuklappen und eine Spalte mit Verweisen. Gewählte Zeilen lassen sich in das Feld darunter ziehen.";

    public override string Stichworte => "DataGrid HeadersVisibility ShowRowNumbers FrozenColumnCount RowDetailsTemplate GroupColumns DataGridHyperlinkColumn CanUserDragRows Ziehen Ablegen";

    public override string Datei => nameof(DataGridAusbauSeite);

    public override UIElement Baue()
    {
        string[] orte = ["Bern", "Basel", "Luzern", "Chur"];
        var projekte = new Projekt[200];
        for (int i = 0; i < projekte.Length; i++)
            projekte[i] = new Projekt($"Projekt {i + 1}", $"Leitung {(i % 7) + 1}", orte[i % 4], $"https://kuonen.org/projekt/{i + 1}", $"Notiz zu Projekt {i + 1}: im Plan.");
        var grid = new DataGrid
        {
            Width = 560,
            Height = 240,
            ItemsSource = projekte,
            HeadersVisibility = DataGridHeadersVisibility.All,
            ShowRowNumbers = true,
            FrozenColumnCount = 1,
            CanUserDragRows = true,
            // Die Details zeigen die Notiz über eine Bindung an die Zeile (Datenkontext = Projekt).
            RowDetailsTemplate = new DataTemplate(_ =>
            {
                var notiz = new TextBlock { Margin = new Thickness(8, 2, 8, 6) };
                notiz.SetBinding(TextBlock.TextProperty, new Binding<Projekt, string>(BindingPath.Stufe<Projekt, string>("Notiz", p => p.Notiz)));
                return notiz;
            }),
        };
        grid.Columns.Add(new DataGridTextColumn { Header = "Name", Width = GridLength.Pixel(120), Binding = Zellbindung.Aus(BindingPath.Stufe<Projekt, string>("Name", p => p.Name), schreibbar: false) });
        grid.Columns.Add(new DataGridTextColumn { Header = "Leitung", Width = GridLength.Pixel(120), Binding = Zellbindung.Aus(BindingPath.Stufe<Projekt, string>("Leitung", p => p.Leitung), schreibbar: false) });
        var ort = new DataGridTextColumn { Header = "Ort", Width = GridLength.Pixel(100), Binding = Zellbindung.Aus(BindingPath.Stufe<Projekt, string>("Ort", p => p.Ort), schreibbar: false) };
        grid.Columns.Add(ort);
        grid.Columns.Add(new DataGridHyperlinkColumn { Header = "Web", Width = GridLength.Pixel(240), Binding = Zellbindung.Aus(BindingPath.Stufe<Projekt, string>("Web", p => p.Web), schreibbar: false) });

        var gruppen = new CheckBox { Content = "Nach Ort gruppieren" };
        gruppen.Checked += (_, _) => grid.GroupColumns.Add(ort);
        gruppen.Unchecked += (_, _) => grid.GroupColumns.Clear();

        // Ein Ziel für gezogene Zeilen: es nimmt den Text (TSV) an.
        var abgelegt = new TextBlock { Text = "Gewählte Zeilen hierher ziehen." };
        var ziel = new Border { Height = 60, Width = 560, AllowDrop = true, Background = new SolidColorBrush(Color.FromRgb(240, 244, 250)), Child = abgelegt };
        ziel.DragOver += (_, e) => e.Effects = e.Data.GetText() is null ? DragDropEffects.None : DragDropEffects.Copy;
        ziel.Drop += (_, e) => abgelegt.Text = e.Data.GetText() ?? "";

        var seite = new StackPanel { Spacing = 12 };
        seite.Children.Add(gruppen);
        seite.Children.Add(grid);
        seite.Children.Add(ziel);
        return seite;
    }
}

/// <summary>Ein Projekt der Vorführung.</summary>
public sealed class Projekt(string name, string leitung, string ort, string web, string notiz)
{
    public string Name { get; } = name;

    public string Leitung { get; } = leitung;

    public string Ort { get; } = ort;

    public string Web { get; } = web;

    public string Notiz { get; } = notiz;
}