Zum Inhalt
Kuonen.UI

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.

Vorführung: FlyoutsVorführung: Flyouts

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