Zum Inhalt
Kuonen.UI

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.

Vorführung: AndockenVorführung: Andocken

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 } };
    }
}