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. Mit „Eigene Fenster“ werden schwebende Fenster zu Fenstern des Systems (Windows, X11, macOS), die sich auf einen zweiten Bildschirm ziehen lassen; die Trenner sind auch per Tab und Pfeiltasten bedienbar.


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" />
<CheckBox x:Name="EigeneFenster" Content="Eigene Fenster" VerticalAlignment="Center" />
<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, EigeneFenster);
}
}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. Mit „Eigene Fenster“ werden schwebende Fenster zu Fenstern "
+ "des Systems (Windows, X11, macOS), die sich auf einen zweiten Bildschirm ziehen lassen; die Trenner sind auch per Tab und Pfeiltasten bedienbar.";
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, CheckBox eigeneFenster)
{
eigeneFenster.Click += (_, _) =>
bereich.FloatingWindowMode = eigeneFenster.IsChecked == true ? DockFloatingWindowMode.Native : DockFloatingWindowMode.Inline;
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" };
var eigeneFenster = new CheckBox { Content = "Eigene Fenster", VerticalAlignment = VerticalAlignment.Center };
Verdrahte(bereich, meldung, neu, merken, laden, eigeneFenster);
var leiste = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 8, Children = { neu, merken, laden, eigeneFenster, meldung } };
return new StackPanel { Spacing = 8, Children = { leiste, bereich } };
}
}