Window und Dialoge
Ein Fenster mit Titel, Grösse und Zustand. Ein Fenster mit Owner gehört seinem Besitzer (schliesst mit ihm). ZeigeDialogAsync zeigt es modal: der Besitzer ist gesperrt, bis DialogResult gesetzt oder das Fenster geschlossen wird. Closing kann das Schliessen abbrechen.


KXAML
WindowSeite.kxaml
<StackPanel xmlns="https://ui.kuonen.org/kxaml"
xmlns:x="https://ui.kuonen.org/kxaml/x"
x:Class="Kuonen.UI.Galerie.Seiten.WindowVorfuehrung"
Spacing="12">
<StackPanel Orientation="Horizontal" Spacing="8">
<!-- Ein gewöhnliches, besessenes Fenster und ein modaler Dialog mit Ergebnis; beide baut das Code-Behind. -->
<Button x:Name="Neu" Content="Neues Fenster" Click="Neu_Click" />
<Button x:Name="Dialog" Content="Dialog …" Style="{x:Static Fluent.AkzentButton}" Click="Dialog_Click" />
</StackPanel>
<CheckBox x:Name="Nachfragen" Content="Beim Schliessen nachfragen (Closing bricht ab)" />
<TextBlock x:Name="Meldung" Text="Noch kein Fenster geöffnet." TextWrapping="Wrap" />
</StackPanel>WindowSeite.kxaml.cs
using Kuonen.UI;
using Kuonen.UI.Controls;
using Kuonen.UI.Ereignisse;
using Kuonen.UI.Layout;
using Kuonen.UI.Themes;
namespace Kuonen.UI.Galerie.Seiten;
public sealed partial class WindowSeite
{
protected override Func<UIElement>? KxamlFabrik => () => new WindowVorfuehrung();
}
/// <summary>KXAML-Fassung der Window-Seite: die Seite steht in WindowSeite.kxaml, die Fenster entstehen hier beim Klick.</summary>
public sealed partial class WindowVorfuehrung
{
public WindowVorfuehrung() => InitializeComponent();
// Das Fenster, in dem diese Seite steht: Besitzer der neuen Fenster.
private static Window? FensterVon(Visual element)
{
for (Visual? v = element; v is not null; v = v.VisualParent)
if (v is Window fenster) return fenster;
return null;
}
// Das Unterfenster folgt dem Theme seines Besitzers, solange es offen ist (Hell/Dunkel der Galerie, Systemwechsel).
private static void FolgeTheme(Window besitzer, Window fenster)
{
fenster.Theme = besitzer.Theme;
var abo = besitzer.Abonniere(Window.ThemeProperty, () => fenster.Theme = besitzer.Theme);
fenster.Closed += (_, _) => abo.Dispose();
}
private void Neu_Click(object sender, RoutedEventArgs e)
{
if (FensterVon(Neu) is not { } besitzer) return;
var zu = new Button { Content = "Schliessen", HorizontalAlignment = HorizontalAlignment.Left };
var inhalt = new StackPanel { Spacing = 12, Margin = new Thickness(16) };
inhalt.Children.Add(new TextBlock { Text = "Ein Fenster der Galerie. Es schliesst mit seinem Besitzer." });
inhalt.Children.Add(zu);
var fenster = new Window { Title = "Neues Fenster", Width = 360, Height = 160, Owner = besitzer, Content = inhalt };
FolgeTheme(besitzer, fenster);
bool abgebrochen = false;
fenster.Closing += (_, a) =>
{
if (Nachfragen.IsChecked != true || abgebrochen) return;
a.Cancel = true; // einmal abbrechen; der nächste Versuch schliesst
abgebrochen = true;
Meldung.Text = "Schliessen abgebrochen (Closing). Noch einmal versuchen schliesst.";
};
fenster.Closed += (_, _) => Meldung.Text = "Fenster geschlossen.";
zu.Click += (_, _) => fenster.Close();
fenster.Show();
Meldung.Text = "Fenster geöffnet.";
}
private async void Dialog_Click(object sender, RoutedEventArgs e)
{
if (FensterVon(Dialog) is not { } besitzer) return;
var ja = new Button { Content = "Ja", Style = Fluent.AkzentButton, MinWidth = 80 };
var nein = new Button { Content = "Nein", MinWidth = 80 };
var knoepfe = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 8, HorizontalAlignment = HorizontalAlignment.Right };
knoepfe.Children.Add(ja);
knoepfe.Children.Add(nein);
var inhalt = new DockPanel { Margin = new Thickness(16) };
DockPanel.SetDock(knoepfe, Dock.Bottom);
inhalt.Children.Add(knoepfe);
inhalt.Children.Add(new TextBlock { Text = "Änderungen übernehmen?", TextWrapping = TextWrapping.Wrap });
var fenster = new Window { Title = "Frage", Width = 320, Height = 140, Owner = besitzer, Content = inhalt };
FolgeTheme(besitzer, fenster);
ja.Click += (_, _) => fenster.DialogResult = true;
nein.Click += (_, _) => fenster.DialogResult = false;
Meldung.Text = "Dialog offen; das Hauptfenster ist gesperrt.";
bool? ergebnis = await fenster.ZeigeDialogAsync();
Meldung.Text = ergebnis switch { true => "Antwort: Ja.", false => "Antwort: Nein.", null => "Ohne Antwort geschlossen." };
}
}C#
WindowSeite.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="Window"/> und modale Dialoge.</summary>
public sealed partial class WindowSeite : GalerieSeite
{
public override string Titel => "Window und Dialoge";
public override string Beschreibung =>
"Ein Fenster mit Titel, Grösse und Zustand. Ein Fenster mit Owner gehört seinem Besitzer (schliesst mit ihm). "
+ "ZeigeDialogAsync zeigt es modal: der Besitzer ist gesperrt, bis DialogResult gesetzt oder das Fenster "
+ "geschlossen wird. Closing kann das Schliessen abbrechen.";
public override string Stichworte => "Fenster Dialog modal Owner Besitzer DialogResult ZeigeDialogAsync Closing Schliessen abbrechen WindowState";
public override string Datei => nameof(WindowSeite);
public override UIElement Baue()
{
var meldung = new TextBlock { Text = "Noch kein Fenster geöffnet.", TextWrapping = TextWrapping.Wrap };
// Das Fenster, in dem diese Seite steht: Besitzer der neuen Fenster.
static Window? FensterVon(Visual element)
{
for (Visual? v = element; v is not null; v = v.VisualParent)
if (v is Window fenster) return fenster;
return null;
}
// Das Unterfenster folgt dem Theme seines Besitzers, solange es offen ist (Hell/Dunkel der Galerie, Systemwechsel).
static void FolgeTheme(Window besitzer, Window fenster)
{
fenster.Theme = besitzer.Theme;
var abo = besitzer.Abonniere(Window.ThemeProperty, () => fenster.Theme = besitzer.Theme);
fenster.Closed += (_, _) => abo.Dispose();
}
var nachfragen = new CheckBox { Content = "Beim Schliessen nachfragen (Closing bricht ab)" };
// Ein gewöhnliches, besessenes Fenster.
var neu = new Button { Content = "Neues Fenster" };
neu.Click += (_, _) =>
{
if (FensterVon(neu) is not { } besitzer) return;
var zu = new Button { Content = "Schliessen", HorizontalAlignment = HorizontalAlignment.Left };
var inhalt = new StackPanel { Spacing = 12, Margin = new Thickness(16) };
inhalt.Children.Add(new TextBlock { Text = "Ein Fenster der Galerie. Es schliesst mit seinem Besitzer." });
inhalt.Children.Add(zu);
var fenster = new Window { Title = "Neues Fenster", Width = 360, Height = 160, Owner = besitzer, Content = inhalt };
FolgeTheme(besitzer, fenster);
bool abgebrochen = false;
fenster.Closing += (_, e) =>
{
if (nachfragen.IsChecked != true || abgebrochen) return;
e.Cancel = true; // einmal abbrechen; der nächste Versuch schliesst
abgebrochen = true;
meldung.Text = "Schliessen abgebrochen (Closing). Noch einmal versuchen schliesst.";
};
fenster.Closed += (_, _) => meldung.Text = "Fenster geschlossen.";
zu.Click += (_, _) => fenster.Close();
fenster.Show();
meldung.Text = "Fenster geöffnet.";
};
// Ein modaler Dialog mit Ergebnis.
var dialog = new Button { Content = "Dialog …", Style = Fluent.AkzentButton };
dialog.Click += async (_, _) =>
{
if (FensterVon(dialog) is not { } besitzer) return;
var ja = new Button { Content = "Ja", Style = Fluent.AkzentButton, MinWidth = 80 };
var nein = new Button { Content = "Nein", MinWidth = 80 };
var knoepfe = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 8, HorizontalAlignment = HorizontalAlignment.Right };
knoepfe.Children.Add(ja);
knoepfe.Children.Add(nein);
var inhalt = new DockPanel { Margin = new Thickness(16) };
DockPanel.SetDock(knoepfe, Dock.Bottom);
inhalt.Children.Add(knoepfe);
inhalt.Children.Add(new TextBlock { Text = "Änderungen übernehmen?", TextWrapping = TextWrapping.Wrap });
var fenster = new Window { Title = "Frage", Width = 320, Height = 140, Owner = besitzer, Content = inhalt };
FolgeTheme(besitzer, fenster);
ja.Click += (_, _) => fenster.DialogResult = true;
nein.Click += (_, _) => fenster.DialogResult = false;
meldung.Text = "Dialog offen; das Hauptfenster ist gesperrt.";
bool? ergebnis = await fenster.ZeigeDialogAsync();
meldung.Text = ergebnis switch { true => "Antwort: Ja.", false => "Antwort: Nein.", null => "Ohne Antwort geschlossen." };
};
var reihe = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 8 };
reihe.Children.Add(neu);
reihe.Children.Add(dialog);
var seite = new StackPanel { Spacing = 12 };
seite.Children.Add(reihe);
seite.Children.Add(nachfragen);
seite.Children.Add(meldung);
return seite;
}
}