Zum Inhalt
Kuonen.UI

RelativePanel

Ordnet Kinder relativ zueinander und zum Panel an: RightOf, LeftOf, Above, Below, die bündigen AlignXxxWith und die AlignXxxWithPanel-Kanten. Sind links und rechts gesetzt, spannt sich das Kind auf. Ein Kreis (A rechts von B und B rechts von A) wirft nicht: beide liegen links oben, und eine Meldung geht an Anwendung.UnhandledException.

Vorführung: RelativePanelVorführung: RelativePanel

KXAML

RelativePanelSeite.kxaml
<StackPanel xmlns="https://ui.kuonen.org/kxaml"
            xmlns:x="https://ui.kuonen.org/kxaml/x"
            x:Class="Kuonen.UI.Galerie.Seiten.RelativePanelVorfuehrung"
            Spacing="8">
  <TextBlock Text="Formular: RightOf, Below, AlignLeftWith, AlignRightWithPanel" FontWeight="SemiBold" />
  <!-- Ein Formular: die Felder stehen rechts von ihrer Beschriftung und reichen bis zum Rand des Panels. Bezüge stehen als {x:Reference Name}. -->
  <RelativePanel Width="360" HorizontalAlignment="Left">
    <TextBlock x:Name="NamenText" Text="Name" Margin="0,6,8,0" />
    <TextBox x:Name="NamenFeld" Margin="0,0,0,8" RelativePanel.RightOf="{x:Reference NamenText}" RelativePanel.AlignRightWithPanel="True" />
    <TextBlock x:Name="OrtText" Text="Ort" Margin="0,6,8,0" RelativePanel.Below="{x:Reference NamenFeld}" />
    <TextBox x:Name="OrtFeld" Margin="0,0,0,8" RelativePanel.Below="{x:Reference NamenFeld}" RelativePanel.AlignLeftWith="{x:Reference NamenFeld}"
             RelativePanel.AlignRightWithPanel="True" />
    <Button x:Name="Abbrechen" Content="Abbrechen" RelativePanel.Below="{x:Reference OrtFeld}" RelativePanel.LeftOf="{x:Reference Ok}" />
    <Button x:Name="Ok" Content="OK" Margin="8,0,0,0" RelativePanel.Below="{x:Reference OrtFeld}" RelativePanel.AlignRightWithPanel="True" />
  </RelativePanel>
  <TextBlock Text="Kanten und Mitte des Panels" FontWeight="SemiBold" />
  <!-- Kanten und Mitte des Panels. -->
  <RelativePanel Width="360" Height="120" HorizontalAlignment="Left" Background="#F3F3F3">
    <Border Background="#CCE4F7" CornerRadius="4" Width="90" Height="32">
      <TextBlock Text="Links oben" Foreground="#1B1B1B" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Border>
    <Border Background="#D3F0D4" CornerRadius="4" Width="90" Height="32"
            RelativePanel.AlignHorizontalCenterWithPanel="True" RelativePanel.AlignVerticalCenterWithPanel="True">
      <TextBlock Text="Mitte" Foreground="#1B1B1B" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Border>
    <Border Background="#CCE4F7" CornerRadius="4" Width="90" Height="32"
            RelativePanel.AlignRightWithPanel="True" RelativePanel.AlignBottomWithPanel="True">
      <TextBlock Text="Rechts unten" Foreground="#1B1B1B" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Border>
  </RelativePanel>
  <TextBlock Text="Kreis" FontWeight="SemiBold" />
  <!-- Ein Kreis: B steht rechts von A. Der Knopf macht auch A rechts von B; dann liegen beide links oben, und eine Meldung geht an die Anwendung. -->
  <RelativePanel Width="360" Height="40" HorizontalAlignment="Left">
    <Border x:Name="KreisA" Background="#CCE4F7" CornerRadius="4" Width="90" Height="32">
      <TextBlock Text="A" Foreground="#1B1B1B" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Border>
    <Border x:Name="KreisB" Background="#D3F0D4" CornerRadius="4" Width="130" Height="32" RelativePanel.RightOf="{x:Reference KreisA}">
      <TextBlock Text="B (rechts von A)" Foreground="#1B1B1B" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Border>
  </RelativePanel>
  <Button x:Name="Umschalten" Content="A rechts von B setzen (Kreis)" Click="Umschalten_Click" />
  <TextBlock x:Name="Zustand" Text="Ohne Kreis: B steht rechts von A." />
</StackPanel>
RelativePanelSeite.kxaml.cs
using Kuonen.UI;
using Kuonen.UI.Ereignisse;
using Kuonen.UI.Layout;

namespace Kuonen.UI.Galerie.Seiten;

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

/// <summary>KXAML-Fassung der RelativePanel-Seite: der Baum steht in RelativePanelSeite.kxaml, hier nur das Verhalten.</summary>
public sealed partial class RelativePanelVorfuehrung
{
    public RelativePanelVorfuehrung() => InitializeComponent();

    private void Umschalten_Click(object sender, RoutedEventArgs e)
    {
        bool aus = RelativePanel.GetRightOf(KreisA) is not null;
        RelativePanel.SetRightOf(KreisA, aus ? null : KreisB);
        Umschalten.Content = aus ? "A rechts von B setzen (Kreis)" : "Kreis auflösen";
        Zustand.Text = aus ? "Ohne Kreis: B steht rechts von A." : "Kreis: beide liegen links oben, gemeldet an Anwendung.UnhandledException.";
    }
}

C#

RelativePanelSeite.cs
using Kuonen.UI;
using Kuonen.UI.Controls;
using Kuonen.UI.Layout;
using Kuonen.UI.Media;

namespace Kuonen.UI.Galerie.Seiten;

/// <summary>Galerie-Seite: <see cref="RelativePanel"/>.</summary>
public sealed partial class RelativePanelSeite : GalerieSeite
{
    public override string Titel => "RelativePanel";

    public override string Beschreibung =>
        "Ordnet Kinder relativ zueinander und zum Panel an: RightOf, LeftOf, Above, Below, die bündigen AlignXxxWith und die "
        + "AlignXxxWithPanel-Kanten. Sind links und rechts gesetzt, spannt sich das Kind auf. Ein Kreis (A rechts von B und B rechts von A) "
        + "wirft nicht: beide liegen links oben, und eine Meldung geht an Anwendung.UnhandledException.";

    public override string Stichworte => "Bezüge relativ Formular RightOf LeftOf Above Below Align Panel Kreis Zyklus RelativeLayout";

    public override string Datei => nameof(RelativePanelSeite);

    public override UIElement Baue()
    {
        var blau = new SolidColorBrush(Color.FromRgb(0xCC, 0xE4, 0xF7));
        var gruen = new SolidColorBrush(Color.FromRgb(0xD3, 0xF0, 0xD4));
        var dunkel = new SolidColorBrush(Color.FromRgb(0x1B, 0x1B, 0x1B));

        // Ein Formular: die Felder stehen rechts von ihrer Beschriftung und reichen bis zum Rand des Panels.
        var namenText = new TextBlock { Text = "Name", Margin = new Thickness(0, 6, 8, 0) };
        var namenFeld = new TextBox { Margin = new Thickness(0, 0, 0, 8) };
        var ortText = new TextBlock { Text = "Ort", Margin = new Thickness(0, 6, 8, 0) };
        var ortFeld = new TextBox { Margin = new Thickness(0, 0, 0, 8) };
        var ok = new Button { Content = "OK", Margin = new Thickness(8, 0, 0, 0) };
        var abbrechen = new Button { Content = "Abbrechen" };
        RelativePanel.SetRightOf(namenFeld, namenText);
        RelativePanel.SetAlignRightWithPanel(namenFeld, true);
        RelativePanel.SetBelow(ortText, namenFeld);
        RelativePanel.SetBelow(ortFeld, namenFeld);
        RelativePanel.SetAlignLeftWith(ortFeld, namenFeld);
        RelativePanel.SetAlignRightWithPanel(ortFeld, true);
        RelativePanel.SetBelow(ok, ortFeld);
        RelativePanel.SetAlignRightWithPanel(ok, true);
        RelativePanel.SetBelow(abbrechen, ortFeld);
        RelativePanel.SetLeftOf(abbrechen, ok);
        var formular = new RelativePanel { Width = 360, HorizontalAlignment = HorizontalAlignment.Left };
        formular.Children.Add(namenText);
        formular.Children.Add(namenFeld);
        formular.Children.Add(ortText);
        formular.Children.Add(ortFeld);
        formular.Children.Add(abbrechen);
        formular.Children.Add(ok);

        // Kanten und Mitte des Panels.
        Border Feld(string text, Brush fuellung) => new()
        {
            Background = fuellung, CornerRadius = new CornerRadius(4), Width = 90, Height = 32,
            Child = new TextBlock { Text = text, Foreground = dunkel, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center },
        };
        var links = Feld("Links oben", blau);
        var mitte = Feld("Mitte", gruen);
        var unten = Feld("Rechts unten", blau);
        RelativePanel.SetAlignHorizontalCenterWithPanel(mitte, true);
        RelativePanel.SetAlignVerticalCenterWithPanel(mitte, true);
        RelativePanel.SetAlignRightWithPanel(unten, true);
        RelativePanel.SetAlignBottomWithPanel(unten, true);
        var rand = new RelativePanel { Width = 360, Height = 120, HorizontalAlignment = HorizontalAlignment.Left, Background = new SolidColorBrush(Color.FromRgb(0xF3, 0xF3, 0xF3)) };
        rand.Children.Add(links);
        rand.Children.Add(mitte);
        rand.Children.Add(unten);

        // Ein Kreis: B steht rechts von A. Der Knopf macht auch A rechts von B; dann liegen beide links oben, und eine Meldung geht an die Anwendung.
        var a = Feld("A", blau);
        var b = Feld("B (rechts von A)", gruen);
        b.Width = 130;
        RelativePanel.SetRightOf(b, a);
        var kreis = new RelativePanel { Width = 360, Height = 40, HorizontalAlignment = HorizontalAlignment.Left };
        kreis.Children.Add(a);
        kreis.Children.Add(b);
        var zustand = new TextBlock { Text = "Ohne Kreis: B steht rechts von A." };
        var umschalten = new Button { Content = "A rechts von B setzen (Kreis)" };
        umschalten.Click += (_, _) =>
        {
            bool aus = RelativePanel.GetRightOf(a) is not null;
            RelativePanel.SetRightOf(a, aus ? null : b);
            umschalten.Content = aus ? "A rechts von B setzen (Kreis)" : "Kreis auflösen";
            zustand.Text = aus ? "Ohne Kreis: B steht rechts von A." : "Kreis: beide liegen links oben, gemeldet an Anwendung.UnhandledException.";
        };

        var seite = new StackPanel { Spacing = 8 };
        seite.Children.Add(new TextBlock { Text = "Formular: RightOf, Below, AlignLeftWith, AlignRightWithPanel", FontWeight = 600 });
        seite.Children.Add(formular);
        seite.Children.Add(new TextBlock { Text = "Kanten und Mitte des Panels", FontWeight = 600 });
        seite.Children.Add(rand);
        seite.Children.Add(new TextBlock { Text = "Kreis", FontWeight = 600 });
        seite.Children.Add(kreis);
        seite.Children.Add(umschalten);
        seite.Children.Add(zustand);
        return seite;
    }
}