Ergebnisraster
Das DataGrid wie das Ergebnisraster von SSMS: Zellbereiche wählen (Klick, Umschalt, Strg, Ziehen), Strg+C kopiert, Strg+Umschalt+C mit Köpfen, Strg+V fügt ein. Die Filterzeile filtert je Spalte („enthält“ oder mit = < > vergleichen), Entf löscht Zeilen, Pfeil runter in der letzten Zeile legt eine an. Unten der Export als CSV oder JSON.


KXAML
ErgebnisrasterSeite.kxaml
<StackPanel xmlns="https://ui.kuonen.org/kxaml"
xmlns:x="https://ui.kuonen.org/kxaml/x"
x:Class="Kuonen.UI.Galerie.Seiten.ErgebnisrasterVorfuehrung"
Spacing="12">
<StackPanel Orientation="Horizontal" Spacing="12">
<CheckBox x:Name="Zellen" Content="Zellen wählen" />
<CheckBox x:Name="Filter" Content="Filterzeile" />
<Button x:Name="Neu" Content="Neue Zeile" />
<Button x:Name="Loeschen" Content="Löschen" />
<Button x:Name="Csv" Content="Als CSV" />
<Button x:Name="Json" Content="Als JSON" />
<TextBlock x:Name="Stand" VerticalAlignment="Center" />
</StackPanel>
<!-- Die Spalten (darunter eine Auswahlliste mit Anzeigefunktion) setzt das Code-Behind; so teilen sich beide Fassungen das Verhalten. -->
<DataGrid x:Name="Raster" Width="640" Height="300" />
<TextBox x:Name="Ausgabe" Width="640" Height="140" AcceptsReturn="True" IsReadOnly="True" FontFamily="Consolas" />
</StackPanel>ErgebnisrasterSeite.kxaml.cs
using Kuonen.UI;
namespace Kuonen.UI.Galerie.Seiten;
public sealed partial class ErgebnisrasterSeite
{
protected override Func<UIElement>? KxamlFabrik => () => new ErgebnisrasterVorfuehrung();
}
/// <summary>KXAML-Fassung der Seite Ergebnisraster: der Aufbau steht in ErgebnisrasterSeite.kxaml, hier das Verhalten.</summary>
public sealed partial class ErgebnisrasterVorfuehrung
{
public ErgebnisrasterVorfuehrung()
{
InitializeComponent();
ErgebnisrasterSeite.Verdrahte(Raster, Zellen, Filter, Neu, Loeschen, Csv, Json, Ausgabe, Stand);
}
}C#
ErgebnisrasterSeite.cs
using System.Collections.ObjectModel;
using System.Globalization;
using Kuonen.UI;
using Kuonen.UI.Bindung;
using Kuonen.UI.Controls;
using Kuonen.UI.Layout;
using Kuonen.UI.Text;
namespace Kuonen.UI.Galerie.Seiten;
/// <summary>Galerie-Seite: das DataGrid als Ergebnisraster eines SQL-Managers (Plan T): Zellbereiche, Filter, Zeilen anlegen und löschen, Export.</summary>
public sealed partial class ErgebnisrasterSeite : GalerieSeite
{
public override string Titel => "Ergebnisraster";
public override string Beschreibung =>
"Das DataGrid wie das Ergebnisraster von SSMS: Zellbereiche wählen (Klick, Umschalt, Strg, Ziehen), Strg+C kopiert, Strg+Umschalt+C mit Köpfen, "
+ "Strg+V fügt ein. Die Filterzeile filtert je Spalte („enthält“ oder mit = < > vergleichen), Entf löscht Zeilen, Pfeil runter in der letzten "
+ "Zeile legt eine an. Unten der Export als CSV oder JSON.";
public override string Stichworte => "DataGrid Ergebnisraster SQL SSMS Zellen Auswahl Filter Export CSV JSON Kopieren Einfügen Zwischenablage Löschen";
public override string Datei => nameof(ErgebnisrasterSeite);
internal static readonly string[] Status = ["offen", "geliefert", "storniert"];
/// <summary>Eine Bestellung (eine Zeile des Ergebnisses).</summary>
public sealed class Bestellung
{
public string Kunde { get; set; } = "";
public int Menge { get; set; }
public decimal Betrag { get; set; }
public string? Stand { get; set; }
public bool Bezahlt { get; set; }
}
internal static ObservableCollection<Bestellung> Daten()
{
string[] kunden = ["Muster AG", "Beispiel GmbH", "Kuonen", "Alpenblick", "Seeblick", "Talstation"];
var liste = new ObservableCollection<Bestellung>();
for (int i = 0; i < 40; i++)
liste.Add(new Bestellung { Kunde = kunden[i % kunden.Length], Menge = 1 + (i * 7 % 12), Betrag = 12.5m * (1 + (i % 9)), Stand = Status[i % 3], Bezahlt = i % 4 == 0 });
return liste;
}
/// <summary>Das Verhalten beider Fassungen: Spalten, Schalter und Export.</summary>
internal static void Verdrahte(DataGrid raster, CheckBox zellen, CheckBox filter, Button neu, Button loeschen, Button csv, Button json, TextBox ausgabe, TextBlock stand)
{
raster.Columns.Add(new DataGridTextColumn
{
Header = "Kunde", Width = GridLength.Star(), SortMemberPath = "Kunde",
Binding = Zellbindung.Aus(BindingPath.Stufe<Bestellung, string>("Kunde", static b => b.Kunde, static (b, w) => b.Kunde = w ?? "")),
});
raster.Columns.Add(new DataGridTextColumn
{
Header = "Menge", Width = GridLength.Pixel(80), SortMemberPath = "Menge", TextAlignment = TextAusrichtung.Ende,
Binding = Zellbindung.Aus(BindingPath.Stufe<Bestellung, int>("Menge", static b => b.Menge, static (b, w) => b.Menge = w)),
});
raster.Columns.Add(new DataGridTextColumn
{
Header = "Betrag", Width = GridLength.Pixel(100), SortMemberPath = "Betrag", Format = "N2", TextAlignment = TextAusrichtung.Ende,
Binding = Zellbindung.Aus(BindingPath.Stufe<Bestellung, decimal>("Betrag", static b => b.Betrag, static (b, w) => b.Betrag = w)),
});
raster.Columns.Add(new DataGridComboBoxColumn
{
Header = "Stand", Width = GridLength.Pixel(110), SortMemberPath = "Stand", ItemsSource = Status,
Binding = Zellbindung.Aus(BindingPath.Stufe<Bestellung, string?>("Stand", static b => b.Stand, static (b, w) => b.Stand = w)),
});
raster.Columns.Add(new DataGridCheckBoxColumn
{
Header = "Bezahlt", Width = GridLength.Pixel(80), SortMemberPath = "Bezahlt",
Binding = Zellbindung.Aus(BindingPath.Stufe<Bestellung, bool>("Bezahlt", static b => b.Bezahlt, static (b, w) => b.Bezahlt = w)),
});
raster.ItemsSource = Daten();
raster.CanUserAddRows = true;
raster.NewItemFactory = static () => new Bestellung { Kunde = "Neu", Stand = Status[0] };
raster.SelectionUnit = DataGridSelectionUnit.Cell;
zellen.IsChecked = true;
zellen.Checked += (_, _) => raster.SelectionUnit = DataGridSelectionUnit.Cell;
zellen.Unchecked += (_, _) => raster.SelectionUnit = DataGridSelectionUnit.FullRow;
filter.Checked += (_, _) => raster.ShowFilterRow = true;
filter.Unchecked += (_, _) => raster.ShowFilterRow = false;
neu.Click += (_, _) => raster.AddNewRow();
loeschen.Click += (_, _) => raster.DeleteSelectedRows();
csv.Click += (_, _) => Exportiere(raster, DataGridExportFormat.Csv, ausgabe);
json.Click += (_, _) => Exportiere(raster, DataGridExportFormat.Json, ausgabe);
void Zaehle() => stand.Text = $"{raster.ZeilenAnzahl.ToString(CultureInfo.CurrentCulture)} Zeilen";
raster.SelectionChanged += (_, _) => Zaehle();
Zaehle();
}
// Exportiert die Auswahl (ohne Auswahl alles) in das Ausgabefeld.
private static void Exportiere(DataGrid raster, DataGridExportFormat format, TextBox ausgabe)
{
var text = new StringWriter();
DataGridExport.Schreibe(raster, text, format, nurAuswahl: raster.Auswahl.Anzahl > 0);
ausgabe.Text = text.ToString();
}
public override UIElement Baue()
{
var zellen = new CheckBox { Content = "Zellen wählen" };
var filter = new CheckBox { Content = "Filterzeile" };
var neu = new Button { Content = "Neue Zeile" };
var loeschen = new Button { Content = "Löschen" };
var csv = new Button { Content = "Als CSV" };
var json = new Button { Content = "Als JSON" };
var stand = new TextBlock { VerticalAlignment = VerticalAlignment.Center };
var raster = new DataGrid { Width = 640, Height = 300 };
var ausgabe = new TextBox { Width = 640, Height = 140, AcceptsReturn = true, IsReadOnly = true, FontFamily = new("Consolas") };
Verdrahte(raster, zellen, filter, neu, loeschen, csv, json, ausgabe, stand);
var leiste = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 12, Children = { zellen, filter, neu, loeschen, csv, json, stand } };
return new StackPanel { Spacing = 12, Children = { leiste, raster, ausgabe } };
}
}