using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace DeskCore;
/// Dialoge im Stil eines Windows-11-ContentDialogs.
public static class Dialog
{
public static bool Confirm(Window owner, string title, string message, string primary = "OK", string? secondary = "Abbrechen") =>
Show(owner, title, Text(message), primary, secondary, null);
public static void Info(Window owner, string title, string message) =>
Show(owner, title, Text(message), "OK", null, null);
/// Eingabedialog. validate gibt eine Fehlermeldung oder null zurück.
public static string? Prompt(Window owner, string title, string label, string initial, string primary, Func validate)
{
var box = new TextBox { Text = initial, Margin = new Thickness(0, 8, 0, 0) };
var panel = new StackPanel();
panel.Children.Add(Text(label, secondary: true));
panel.Children.Add(box);
var ok = Show(owner, title, panel, primary, "Abbrechen", () => validate(box.Text), box);
return ok ? box.Text.Trim() : null;
}
public static TextBlock Text(string text, bool secondary = false) => new()
{
Text = text, TextWrapping = TextWrapping.Wrap, LineHeight = 20,
Foreground = (Brush)Application.Current.Resources[secondary ? "TextSecondaryBrush" : "TextBrush"],
};
/// Allgemeiner Dialog mit beliebigem Inhalt. validate: Fehlermeldung oder null.
public static bool Show(Window owner, string title, UIElement content, string primary, string? secondary,
Func? validate, IInputElement? focus = null, double width = 448)
{
var res = Application.Current.Resources;
var error = new TextBlock
{
Foreground = (Brush)res["DangerBrush"], FontSize = 12, Margin = new Thickness(0, 8, 0, 0),
TextWrapping = TextWrapping.Wrap, Visibility = Visibility.Collapsed,
};
var body = new StackPanel { Margin = new Thickness(24, 22, 24, 24) };
body.Children.Add(new TextBlock
{
Text = title, FontSize = 20, FontWeight = FontWeights.SemiBold, Margin = new Thickness(0, 0, 0, 12),
FontFamily = (FontFamily)res["DisplayFont"], TextWrapping = TextWrapping.Wrap,
});
body.Children.Add(content);
body.Children.Add(error);
var ok = new Button { Content = primary, IsDefault = true, Style = (Style)res["AccentButton"] };
var footer = new Grid { Margin = new Thickness(24) };
footer.ColumnDefinitions.Add(new ColumnDefinition());
footer.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(8) });
footer.ColumnDefinitions.Add(new ColumnDefinition());
if (secondary is not null)
{
var cancel = new Button { Content = secondary, IsCancel = true };
Grid.SetColumn(cancel, 2);
footer.Children.Add(cancel);
}
else Grid.SetColumn(ok, 2); // einzelner Button rechts, wie bei Windows 11
footer.Children.Add(ok);
var layout = new DockPanel();
var footerBorder = new Border
{
Background = (Brush)res["DialogFooterBrush"], Child = footer,
BorderBrush = (Brush)res["FlyoutStrokeBrush"], BorderThickness = new Thickness(0, 1, 0, 0),
CornerRadius = new CornerRadius(0, 0, 8, 8),
};
DockPanel.SetDock(footerBorder, Dock.Bottom);
layout.Children.Add(footerBorder);
layout.Children.Add(new ScrollViewer { Content = body, VerticalScrollBarVisibility = ScrollBarVisibility.Auto, MaxHeight = 560 });
var dlg = new Window
{
Owner = owner.IsVisible ? owner : null, Title = title, Width = width + 64, SizeToContent = SizeToContent.Height,
WindowStyle = WindowStyle.None, AllowsTransparency = true, Background = Brushes.Transparent,
ResizeMode = ResizeMode.NoResize, ShowInTaskbar = !owner.IsVisible, Topmost = !owner.IsVisible,
WindowStartupLocation = owner.IsVisible ? WindowStartupLocation.CenterOwner : WindowStartupLocation.CenterScreen,
FontFamily = (FontFamily)res["UiFont"], FontSize = 14,
Foreground = (Brush)res["TextBrush"],
Content = new Border
{
Margin = new Thickness(32), CornerRadius = new CornerRadius(8),
Background = (Brush)res["LayerBrush"],
BorderBrush = (Brush)res["FlyoutStrokeBrush"], BorderThickness = new Thickness(1),
Effect = (System.Windows.Media.Effects.Effect)res["DialogShadow"], Child = layout,
},
};
ok.Click += (_, _) =>
{
if (validate?.Invoke() is { } err)
{
error.Text = err;
error.Visibility = Visibility.Visible;
(focus as UIElement)?.Focus();
return;
}
dlg.DialogResult = true;
};
if (focus is TextBox tb) tb.TextChanged += (_, _) => error.Visibility = Visibility.Collapsed;
dlg.PreviewKeyDown += (_, e) => { if (e.Key == Key.Escape) dlg.Close(); };
dlg.MouseLeftButtonDown += (_, e) => { if (e.ButtonState == MouseButtonState.Pressed) dlg.DragMove(); };
dlg.Loaded += (_, _) =>
{
if (focus is TextBox t) { t.Focus(); t.SelectAll(); }
else if (focus is UIElement u) u.Focus();
else ok.Focus();
};
(owner as MainWindow)?.SetDimmed(true);
try
{
return dlg.ShowDialog() == true;
}
finally
{
(owner as MainWindow)?.SetDimmed(false);
}
}
}