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.


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