Zum Inhalt
Kuonen.UI

Benachrichtigungen

Der Dienst des Fensters (Window.Benachrichtigungen) stapelt Karten in einer Ecke (höchstens fünf, die älteste geht), jede mit Schliessen-Knopf und auf Wunsch einer Klick-Aktion; unter dem Zeiger hält ihre Zeit an. Die Snackbar steht unten in der Mitte, eine zur Zeit, mit einer Aktion. Neue Meldungen sagt ein Bildschirmleser an, Fehler sofort; Fokus und Esc bleiben bei der Anwendung.

Vorführung: BenachrichtigungenVorführung: Benachrichtigungen

KXAML

BenachrichtigungenSeite.kxaml
<StackPanel xmlns="https://ui.kuonen.org/kxaml"
            xmlns:x="https://ui.kuonen.org/kxaml/x"
            x:Class="Kuonen.UI.Galerie.Seiten.BenachrichtigungenVorfuehrung"
            Spacing="8">
  <WrapPanel>
    <Button Content="Erfolg" Margin="0,0,8,8" Click="Zeige_Click" />
    <Button Content="Mit Aktion" Margin="0,0,8,8" Click="Zeige_Click" />
    <Button Content="Fehler" Margin="0,0,8,8" Click="Zeige_Click" />
    <Button Content="Snackbar" Margin="0,0,8,8" Click="Zeige_Click" />
  </WrapPanel>
  <CheckBox Content="Stapel unten links" Click="Ecke_Click" />
  <TextBlock x:Name="Meldung" Text="Bereit." />
</StackPanel>
BenachrichtigungenSeite.kxaml.cs
using Kuonen.UI;
using Kuonen.UI.Ereignisse;

namespace Kuonen.UI.Galerie.Seiten;

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

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

    private void Zeige_Click(object sender, RoutedEventArgs e) => BenachrichtigungenSeite.Zeige(sender, Meldung);

    private void Ecke_Click(object sender, RoutedEventArgs e) => BenachrichtigungenSeite.Ecke(sender);
}

C#

BenachrichtigungenSeite.cs
using Kuonen.UI;
using Kuonen.UI.Controls;
using Kuonen.UI.Layout;

namespace Kuonen.UI.Galerie.Seiten;

/// <summary>Galerie-Seite: <see cref="Benachrichtigungen"/> mit Karten und <see cref="Snackbar"/>.</summary>
public sealed partial class BenachrichtigungenSeite : GalerieSeite
{
    public override string Titel => "Benachrichtigungen";

    public override string Beschreibung =>
        "Der Dienst des Fensters (Window.Benachrichtigungen) stapelt Karten in einer Ecke (höchstens fünf, die älteste geht), jede mit Schliessen-Knopf "
        + "und auf Wunsch einer Klick-Aktion; unter dem Zeiger hält ihre Zeit an. Die Snackbar steht unten in der Mitte, eine zur Zeit, mit einer Aktion. "
        + "Neue Meldungen sagt ein Bildschirmleser an, Fehler sofort; Fokus und Esc bleiben bei der Anwendung.";

    public override string Stichworte =>
        "Benachrichtigung Notification Toast Snackbar Meldung Karte NotificationCard Erfolg Warnung Fehler Rückgängig Ecke NotificationPosition";

    public override string Datei => nameof(BenachrichtigungenSeite);

    /// <summary>Zeigt zu einem der Knöpfe die passende Benachrichtigung (der Knopf trägt die Art im Inhalt).</summary>
    internal static void Zeige(object? sender, TextBlock meldung)
    {
        if (sender is not Button { Content: string art } knopf || Benachrichtigungen.Von(knopf) is not { } dienst) return;
        switch (art)
        {
            case "Erfolg":
                dienst.Zeige(new Benachrichtigung("Gespeichert", "Die Welt wurde gesichert.", NotificationType.Success));
                break;
            case "Mit Aktion":
                dienst.Zeige(new Benachrichtigung("Neue Version", "Klicken zum Laden.") { Aktion = () => meldung.Text = "Aktion der Karte ausgeführt." });
                break;
            case "Fehler":
                dienst.Zeige(new Benachrichtigung("Fehler", "Die Datei ist gesperrt.", NotificationType.Error) { Dauer = TimeSpan.Zero });
                break;
            case "Snackbar":
                dienst.ZeigeSnackbar("Block gelöscht", "Rückgängig", () => meldung.Text = "Rückgängig gemacht.");
                break;
        }
    }

    /// <summary>Wechselt die Ecke des Stapels.</summary>
    internal static void Ecke(object? sender)
    {
        if (sender is CheckBox box && Benachrichtigungen.Von(box) is { } dienst)
            dienst.Ecke = box.IsChecked == true ? NotificationPosition.BottomLeft : NotificationPosition.TopRight;
    }

    public override UIElement Baue()
    {
        var meldung = new TextBlock { Text = "Bereit." };
        var knoepfe = new WrapPanel();
        foreach (var art in new[] { "Erfolg", "Mit Aktion", "Fehler", "Snackbar" })
        {
            var knopf = new Button { Content = art, Margin = new Thickness(0, 0, 8, 8) };
            knopf.Click += (s, _) => Zeige(s, meldung);
            knoepfe.Children.Add(knopf);
        }
        var unten = new CheckBox { Content = "Stapel unten links" };
        unten.Click += (s, _) => Ecke(s);

        var seite = new StackPanel { Spacing = 8 };
        seite.Children.Add(knoepfe);
        seite.Children.Add(unten);
        seite.Children.Add(meldung);
        return seite;
    }
}