Flyouts
Ein Flyout hängt an einer Schaltfläche (Button.Flyout) und schliesst mit Esc oder einem Klick daneben; der Fokus geht hinein und zurück. Ein Menü-Flyout führt Einträge mit Tastenkürzel, Umschalter, Radiogruppe, Trenner und Untermenü. Das Kontext-Flyout der Fläche öffnet mit Rechtsklick, langem Drücken, Umschalt+F10 oder der Menütaste am Zeiger.


KXAML
FlyoutSeite.kxaml
<StackPanel xmlns="https://ui.kuonen.org/kxaml"
xmlns:x="https://ui.kuonen.org/kxaml/x"
x:Class="Kuonen.UI.Galerie.Seiten.FlyoutVorfuehrung"
Spacing="12">
<StackPanel Orientation="Horizontal" Spacing="8">
<Button Content="Info">
<Button.Flyout>
<Flyout>
<TextBlock Text="Esc oder ein Klick daneben schliesst mich." TextWrapping="Wrap" MaxWidth="220" />
</Flyout>
</Button.Flyout>
</Button>
<Button Content="Ansicht">
<Button.Flyout>
<MenuFlyout>
<MenuFlyoutItem Text="Aktualisieren" KeyboardAcceleratorTextOverride="F5" Click="Eintrag_Click" />
<ToggleMenuFlyoutItem Text="Raster" IsChecked="True" Click="Eintrag_Click" />
<MenuFlyoutSeparator />
<RadioMenuFlyoutItem Text="Klein" GroupName="Grösse" Click="Eintrag_Click" />
<RadioMenuFlyoutItem Text="Gross" GroupName="Grösse" IsChecked="True" Click="Eintrag_Click" />
<MenuFlyoutSubItem Text="Sortieren">
<MenuFlyoutItem Text="Nach Name" Click="Eintrag_Click" />
<MenuFlyoutItem Text="Nach Datum" Click="Eintrag_Click" />
</MenuFlyoutSubItem>
</MenuFlyout>
</Button.Flyout>
</Button>
</StackPanel>
<Border Height="80" Background="#CCE4F7">
<FlyoutBase.ContextFlyout>
<MenuFlyout>
<MenuFlyoutItem Text="Kopieren" KeyboardAcceleratorTextOverride="Strg+C" Click="Eintrag_Click" />
<MenuFlyoutItem Text="Einfügen" KeyboardAcceleratorTextOverride="Strg+V" Click="Eintrag_Click" />
</MenuFlyout>
</FlyoutBase.ContextFlyout>
<TextBlock Text="Rechtsklick oder langes Drücken hier" Margin="12" />
</Border>
<TextBlock x:Name="Meldung" Text="Bereit." />
</StackPanel>FlyoutSeite.kxaml.cs
using Kuonen.UI;
using Kuonen.UI.Ereignisse;
namespace Kuonen.UI.Galerie.Seiten;
public sealed partial class FlyoutSeite
{
protected override Func<UIElement>? KxamlFabrik => () => new FlyoutVorfuehrung();
}
/// <summary>KXAML-Fassung der Flyout-Seite: der Baum steht in FlyoutSeite.kxaml, hier das Verhalten.</summary>
public sealed partial class FlyoutVorfuehrung
{
public FlyoutVorfuehrung() => InitializeComponent();
private void Eintrag_Click(object sender, RoutedEventArgs e) => Meldung.Text = FlyoutSeite.Gewaehlt(sender);
}C#
FlyoutSeite.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="Flyout"/>, <see cref="MenuFlyout"/> und <see cref="FlyoutBase.ContextFlyoutProperty"/>.</summary>
public sealed partial class FlyoutSeite : GalerieSeite
{
public override string Titel => "Flyouts";
public override string Beschreibung =>
"Ein Flyout hängt an einer Schaltfläche (Button.Flyout) und schliesst mit Esc oder einem Klick daneben; der Fokus geht hinein und zurück. Ein "
+ "Menü-Flyout führt Einträge mit Tastenkürzel, Umschalter, Radiogruppe, Trenner und Untermenü. Das Kontext-Flyout der Fläche öffnet mit "
+ "Rechtsklick, langem Drücken, Umschalt+F10 oder der Menütaste am Zeiger.";
public override string Stichworte =>
"Flyout MenuFlyout ContextFlyout Kontextmenü Menü Popup Rechtsklick ShowAt Placement MenuFlyoutItem ToggleMenuFlyoutItem RadioMenuFlyoutItem MenuFlyoutSubItem";
public override string Datei => nameof(FlyoutSeite);
internal static string Gewaehlt(object? sender) => sender switch
{
ToggleMenuFlyoutItem { IsChecked: var an } t => $"„{t.Text}“ {(an ? "an" : "aus")}.",
RadioMenuFlyoutItem r => $"Grösse: {r.Text}.",
MenuFlyoutItem m => $"„{m.Text}“ gewählt.",
_ => "",
};
public override UIElement Baue()
{
var meldung = new TextBlock { Text = "Bereit." };
void Melde(MenuFlyoutItem eintrag) => eintrag.Click += (s, _) => meldung.Text = Gewaehlt(s);
var info = new Button
{
Content = "Info",
Flyout = new Flyout { Content = new TextBlock { Text = "Esc oder ein Klick daneben schliesst mich.", TextWrapping = TextWrapping.Wrap, MaxWidth = 220 } },
};
var aktualisieren = new MenuFlyoutItem { Text = "Aktualisieren", KeyboardAcceleratorTextOverride = "F5" };
var raster = new ToggleMenuFlyoutItem { Text = "Raster", IsChecked = true };
var klein = new RadioMenuFlyoutItem { Text = "Klein", GroupName = "Grösse" };
var gross = new RadioMenuFlyoutItem { Text = "Gross", GroupName = "Grösse", IsChecked = true };
var name = new MenuFlyoutItem { Text = "Nach Name" };
var datum = new MenuFlyoutItem { Text = "Nach Datum" };
foreach (var e in new MenuFlyoutItem[] { aktualisieren, raster, klein, gross, name, datum }) Melde(e);
var ansicht = new Button
{
Content = "Ansicht",
Flyout = new MenuFlyout
{
Items = { aktualisieren, raster, new MenuFlyoutSeparator(), klein, gross, new MenuFlyoutSubItem { Text = "Sortieren", Items = { name, datum } } },
},
};
var knoepfe = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 8 };
knoepfe.Children.Add(info);
knoepfe.Children.Add(ansicht);
var kopieren = new MenuFlyoutItem { Text = "Kopieren", KeyboardAcceleratorTextOverride = "Strg+C" };
var einfuegen = new MenuFlyoutItem { Text = "Einfügen", KeyboardAcceleratorTextOverride = "Strg+V" };
Melde(kopieren);
Melde(einfuegen);
var flaeche = new Border
{
Height = 80,
Background = new SolidColorBrush(Color.FromRgb(0xCC, 0xE4, 0xF7)),
Child = new TextBlock { Text = "Rechtsklick oder langes Drücken hier", Margin = new Thickness(12) },
};
FlyoutBase.SetContextFlyout(flaeche, new MenuFlyout { Items = { kopieren, einfuegen } });
var seite = new StackPanel { Spacing = 12 };
seite.Children.Add(knoepfe);
seite.Children.Add(flaeche);
seite.Children.Add(meldung);
return seite;
}
}