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