Popup
Ein Inhalt über allem anderen im Fenster, an ein Ziel gelegt (unten, oben, rechts, links, mittig). Passt er nicht, klappt er um. Mit StaysOpen = false schliesst ein Klick daneben oder Escape; der Fokus kehrt zurück.


KXAML
PopupSeite.kxaml
<StackPanel xmlns="https://ui.kuonen.org/kxaml"
xmlns:x="https://ui.kuonen.org/kxaml/x"
x:Class="Kuonen.UI.Galerie.Seiten.PopupVorfuehrung"
Spacing="12">
<!-- Lage wählen. -->
<StackPanel Orientation="Horizontal" Spacing="12">
<RadioButton Content="Unten" GroupName="PopupLage" IsChecked="True" Checked="Lage_Checked" />
<RadioButton Content="Oben" GroupName="PopupLage" IsChecked="False" Checked="Lage_Checked" />
<RadioButton Content="Rechts" GroupName="PopupLage" IsChecked="False" Checked="Lage_Checked" />
<RadioButton Content="Links" GroupName="PopupLage" IsChecked="False" Checked="Lage_Checked" />
<RadioButton Content="Mittig" GroupName="PopupLage" IsChecked="False" Checked="Lage_Checked" />
</StackPanel>
<!-- Bleibt offen: schliesst nur über die Schaltfläche. -->
<CheckBox x:Name="Bleibt" Content="StaysOpen (schliesst nicht bei Klick daneben)" Click="Bleibt_Click" />
<StackPanel Orientation="Horizontal" Spacing="16" Margin="160,40,0,40">
<Button x:Name="Oeffner" Content="Popup öffnen" Click="Oeffner_Click" />
<!-- PlacementTarget verweist mit x:Reference auf die Schaltfläche. -->
<Popup x:Name="Fenster" PlacementTarget="{x:Reference Oeffner}" Placement="Bottom" VerticalOffset="4" StaysOpen="False" Opened="Popup_Opened" Closed="Popup_Closed">
<!-- Der Inhalt: ein Rahmen in den QuickInfo-Farben des Themes (DynamicResource folgt dem Theme) mit zwei Kästchen. -->
<Border CornerRadius="8" BorderThickness="1">
<Border.Style>
<Style TargetType="Border">
<Setter Property="Background" Value="{DynamicResource Fluent.Farben.ToolTipFlaeche}" />
<Setter Property="BorderBrush" Value="{DynamicResource Fluent.Farben.ToolTipRand}" />
</Style>
</Border.Style>
<StackPanel Spacing="6" Margin="12">
<TextBlock Text="Optionen" FontWeight="SemiBold" />
<CheckBox Content="Rechtschreibung prüfen" />
<CheckBox Content="Automatisch speichern" IsChecked="True" />
<Button Content="Schliessen" Click="Schliessen_Click" />
</StackPanel>
</Border>
</Popup>
</StackPanel>
<TextBlock x:Name="Meldung" Text="Geschlossen." />
</StackPanel>PopupSeite.kxaml.cs
using Kuonen.UI;
using Kuonen.UI.Controls;
using Kuonen.UI.Ereignisse;
namespace Kuonen.UI.Galerie.Seiten;
public sealed partial class PopupSeite
{
protected override Func<UIElement>? KxamlFabrik => () => new PopupVorfuehrung();
}
/// <summary>KXAML-Fassung der Popup-Seite: der Baum steht in PopupSeite.kxaml, hier nur das Verhalten.</summary>
public sealed partial class PopupVorfuehrung
{
public PopupVorfuehrung() => InitializeComponent();
private void Lage_Checked(object sender, RoutedEventArgs e) => Fenster.Placement = (string?)((RadioButton)sender).Content switch
{
"Oben" => PlacementMode.Top,
"Rechts" => PlacementMode.Right,
"Links" => PlacementMode.Left,
"Mittig" => PlacementMode.Center,
_ => PlacementMode.Bottom,
};
private void Bleibt_Click(object sender, RoutedEventArgs e) => Fenster.StaysOpen = Bleibt.IsChecked == true;
private void Oeffner_Click(object sender, RoutedEventArgs e) => Fenster.IsOpen = !Fenster.IsOpen;
private void Schliessen_Click(object sender, RoutedEventArgs e) => Fenster.IsOpen = false;
private void Popup_Opened(object? sender, EventArgs e) => Meldung.Text = "Offen (Klick daneben oder Escape schliesst).";
private void Popup_Closed(object? sender, EventArgs e) => Meldung.Text = "Geschlossen.";
}C#
PopupSeite.cs
using Kuonen.UI;
using Kuonen.UI.Controls;
using Kuonen.UI.Layout;
using Kuonen.UI.Themes;
namespace Kuonen.UI.Galerie.Seiten;
/// <summary>Galerie-Seite: <see cref="Popup"/>.</summary>
public sealed partial class PopupSeite : GalerieSeite
{
public override string Titel => "Popup";
public override string Beschreibung =>
"Ein Inhalt über allem anderen im Fenster, an ein Ziel gelegt (unten, oben, rechts, links, mittig). Passt er "
+ "nicht, klappt er um. Mit StaysOpen = false schliesst ein Klick daneben oder Escape; der Fokus kehrt zurück.";
public override string Stichworte => "Overlay Aufklapper Flyout Placement PlacementTarget StaysOpen leichtes Schliessen IsOpen";
public override string Datei => nameof(PopupSeite);
public override UIElement Baue()
{
var meldung = new TextBlock { Text = "Geschlossen." };
var oeffner = new Button { Content = "Popup öffnen" };
// Der Inhalt des Popups: ein Rahmen in den QuickInfo-Farben des Themes mit zwei Kästchen.
var inhalt = new StackPanel { Spacing = 6, Margin = new Thickness(12) };
inhalt.Children.Add(new TextBlock { Text = "Optionen", FontWeight = 600 });
inhalt.Children.Add(new CheckBox { Content = "Rechtschreibung prüfen" });
inhalt.Children.Add(new CheckBox { Content = "Automatisch speichern", IsChecked = true });
var schliessen = new Button { Content = "Schliessen" };
inhalt.Children.Add(schliessen);
var rahmen = new Border
{
CornerRadius = new CornerRadius(8), BorderThickness = new Thickness(1), Child = inhalt,
Style = new Style(typeof(Border))
.Setze(Border.BackgroundProperty, Fluent.Farben.ToolTipFlaeche)
.Setze(Border.BorderBrushProperty, Fluent.Farben.ToolTipRand),
};
var popup = new Popup { PlacementTarget = oeffner, Placement = PlacementMode.Bottom, VerticalOffset = 4, StaysOpen = false, Child = rahmen };
popup.Opened += (_, _) => meldung.Text = "Offen (Klick daneben oder Escape schliesst).";
popup.Closed += (_, _) => meldung.Text = "Geschlossen.";
oeffner.Click += (_, _) => popup.IsOpen = !popup.IsOpen;
schliessen.Click += (_, _) => popup.IsOpen = false;
// Lage wählen.
var lagen = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 12 };
foreach (var (name, lage) in new[]
{
("Unten", PlacementMode.Bottom), ("Oben", PlacementMode.Top), ("Rechts", PlacementMode.Right),
("Links", PlacementMode.Left), ("Mittig", PlacementMode.Center),
})
{
var feld = new RadioButton { Content = name, GroupName = "PopupLage", IsChecked = lage == PlacementMode.Bottom };
feld.Checked += (_, _) => popup.Placement = lage;
lagen.Children.Add(feld);
}
// Bleibt offen: schliesst nur über die Schaltfläche.
var bleibt = new CheckBox { Content = "StaysOpen (schliesst nicht bei Klick daneben)" };
bleibt.Click += (_, _) => popup.StaysOpen = bleibt.IsChecked == true;
var zeile = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 16, Margin = new Thickness(160, 40, 0, 40) };
zeile.Children.Add(oeffner);
zeile.Children.Add(popup);
var seite = new StackPanel { Spacing = 12 };
seite.Children.Add(lagen);
seite.Children.Add(bleibt);
seite.Children.Add(zeile);
seite.Children.Add(meldung);
return seite;
}
}