Andocken
Ein Arbeitsbereich wie in Visual Studio: Werkzeugfenster links und unten, Dokumente als Reiter in der Mitte. Reiter ziehen ordnet um oder dockt an (Ziele erscheinen, Esc bricht ab), ohne Ziel losgelassen schwebt der Inhalt; der Pin blendet eine Gruppe an den Rand aus. „Anordnung merken“ speichert alles als JSON, „Zurücksetzen“ lädt es wieder.


KXAML
AndockenSeite.kxaml
<StackPanel xmlns="https://ui.kuonen.org/kxaml"
xmlns:x="https://ui.kuonen.org/kxaml/x"
x:Class="Kuonen.UI.Galerie.Seiten.AndockenVorfuehrung"
Spacing="8">
<StackPanel Orientation="Horizontal" Spacing="8">
<Button x:Name="Neu" Content="Neues Dokument" />
<Button x:Name="Merken" Content="Anordnung merken" />
<Button x:Name="Laden" Content="Zurücksetzen" />
<TextBlock x:Name="Meldung" Text="Nichts aktiv." VerticalAlignment="Center" />
</StackPanel>
<DockManager x:Name="Bereich" Height="420">
<DockSplitPanel>
<!-- Werkzeugfenster links: 200 Pixel breit, Reiter erscheinen ab zwei Fenstern unten. -->
<DockTabGroup DockSplitPanel.Length="200">
<DockPane Title="Explorer" Id="Explorer">
<TextBlock Text="Server › Datenbanken › Kunden" Margin="8" />
</DockPane>
<DockPane Title="Eigenschaften" Id="Eigenschaften">
<TextBlock Text="Name: Kunden" Margin="8" />
</DockPane>
</DockTabGroup>
<DockSplitPanel Orientation="Vertical">
<DockTabGroup IsDocumentGroup="True">
<DockDocument Title="Abfrage1.sql" Id="Abfrage1.sql">
<TextBox Text="SELECT * FROM Kunden" AcceptsReturn="True" />
</DockDocument>
<DockDocument Title="Abfrage2.sql" Id="Abfrage2.sql">
<TextBox Text="SELECT * FROM Kunden" AcceptsReturn="True" />
</DockDocument>
</DockTabGroup>
<DockTabGroup DockSplitPanel.Length="110">
<DockPane Title="Ausgabe" Id="Ausgabe">
<TextBlock Text="Befehl erfolgreich." Margin="8" />
</DockPane>
<DockPane Title="Fehlerliste" Id="Fehlerliste">
<TextBlock Text="Keine Fehler." Margin="8" />
</DockPane>
</DockTabGroup>
</DockSplitPanel>
</DockSplitPanel>
</DockManager>
</StackPanel>AndockenSeite.kxaml.cs
using Kuonen.UI;
namespace Kuonen.UI.Galerie.Seiten;
public sealed partial class AndockenSeite
{
protected override Func<UIElement>? KxamlFabrik => () => new AndockenVorfuehrung();
}
/// <summary>KXAML-Fassung der Seite Andocken: die Anordnung steht in AndockenSeite.kxaml, hier das Verhalten.</summary>
public sealed partial class AndockenVorfuehrung
{
public AndockenVorfuehrung()
{
InitializeComponent();
AndockenSeite.Verdrahte(Bereich, Meldung, Neu, Merken, Laden);
}
}C#
AndockenSeite.cs
using Kuonen.UI;
using Kuonen.UI.Controls;
using Kuonen.UI.Layout;
namespace Kuonen.UI.Galerie.Seiten;
/// <summary>Galerie-Seite: das Andock-System (<see cref="DockManager"/>, <see cref="DockSplitPanel"/>, <see cref="DockTabGroup"/>, <see cref="DockPane"/>, <see cref="DockDocument"/>).</summary>
public sealed partial class AndockenSeite : GalerieSeite
{
public override string Titel => "Andocken";
public override string Beschreibung =>
"Ein Arbeitsbereich wie in Visual Studio: Werkzeugfenster links und unten, Dokumente als Reiter in der Mitte. Reiter ziehen ordnet um oder "
+ "dockt an (Ziele erscheinen, Esc bricht ab), ohne Ziel losgelassen schwebt der Inhalt; der Pin blendet eine Gruppe an den Rand aus. "
+ "„Anordnung merken“ speichert alles als JSON, „Zurücksetzen“ lädt es wieder.";
public override string Stichworte =>
"DockManager DockPanel Docking AvalonDock Andocken Werkzeugfenster Dokumente Reiter Tabs Schwebend Floating AutoHide Pin Ausblenden Layout Anordnung speichern";
public override string Datei => nameof(AndockenSeite);
/// <summary>Das Verhalten beider Fassungen: aktiven Inhalt melden, Dokumente anlegen, Anordnung merken und laden.</summary>
internal static void Verdrahte(DockManager bereich, TextBlock meldung, Button neu, Button merken, Button laden)
{
int nummer = bereich.Contents.OfType<DockDocument>().Count();
string? gemerkt = null;
var bekannt = bereich.Contents.ToDictionary(c => c.Id);
bereich.ActiveContentChanged += (_, _) => meldung.Text = bereich.ActiveContent is { } aktiv ? $"Aktiv: {aktiv.Title}" : "Nichts aktiv.";
neu.Click += (_, _) =>
{
var d = Dokument($"Abfrage{++nummer}.sql");
bekannt[d.Id] = d;
bereich.Show(d);
};
merken.Click += (_, _) =>
{
gemerkt = bereich.SaveLayout();
meldung.Text = "Anordnung gemerkt.";
};
laden.Click += (_, _) =>
{
if (gemerkt is null) return;
var ergebnis = bereich.LoadLayout(gemerkt, id => bekannt.GetValueOrDefault(id));
meldung.Text = ergebnis.Success ? "Anordnung geladen." : string.Join(" ", ergebnis.Messages);
};
}
internal static DockDocument Dokument(string titel) =>
new() { Title = titel, Id = titel, Content = new TextBox { Text = "SELECT * FROM Kunden", AcceptsReturn = true } };
private static DockPane Werkzeug(string titel, string text) => new() { Title = titel, Id = titel, Content = new TextBlock { Text = text, Margin = new Thickness(8) } };
public override UIElement Baue()
{
var explorer = Werkzeug("Explorer", "Server › Datenbanken › Kunden");
var eigenschaften = Werkzeug("Eigenschaften", "Name: Kunden");
var links = new DockTabGroup { Items = { explorer, eigenschaften } };
DockSplitPanel.SetLength(links, GridLength.Pixel(200));
var dokumente = new DockTabGroup { IsDocumentGroup = true, Items = { Dokument("Abfrage1.sql"), Dokument("Abfrage2.sql") } };
var unten = new DockTabGroup { Items = { Werkzeug("Ausgabe", "Befehl erfolgreich."), Werkzeug("Fehlerliste", "Keine Fehler.") } };
DockSplitPanel.SetLength(unten, GridLength.Pixel(110));
var mitte = new DockSplitPanel { Orientation = Orientation.Vertical, Children = { dokumente, unten } };
var bereich = new DockManager { Height = 420, Root = new DockSplitPanel { Children = { links, mitte } } };
var meldung = new TextBlock { Text = "Nichts aktiv.", VerticalAlignment = VerticalAlignment.Center };
var neu = new Button { Content = "Neues Dokument" };
var merken = new Button { Content = "Anordnung merken" };
var laden = new Button { Content = "Zurücksetzen" };
Verdrahte(bereich, meldung, neu, merken, laden);
var leiste = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 8, Children = { neu, merken, laden, meldung } };
return new StackPanel { Spacing = 8, Children = { leiste, bereich } };
}
}