Prism对话框之自定义DialogWindow

发布时间 2023-08-26 15:53:11作者: lennox_2019

Prism对话框之自定义DialogWindow

1. 自定义DialogWindow窗体样式

(1)定义DialogWindow窗体类,注意要实现IDialogWindow

/// <summary>
/// CustomDialogWindow.xaml 的交互逻辑
/// </summary>
public partial class CustomDialogWindow : Window, IDialogWindow
{
    public IDialogResult Result { get; set; }
    public CustomDialogWindow()
    {
        InitializeComponent();
        DefaultStyleKey = typeof(CustomDialogWindow);
        CommandBindings.Add(new CommandBinding(SystemCommands.CloseWindowCommand, (_, __) => { SystemCommands.CloseWindow(this); }));
        CommandBindings.Add(new CommandBinding(SystemCommands.MinimizeWindowCommand, (_, __) => { SystemCommands.MinimizeWindow(this); }));
        CommandBindings.Add(new CommandBinding(SystemCommands.MaximizeWindowCommand, (_, __) => { SystemCommands.MaximizeWindow(this); }));
        CommandBindings.Add(new CommandBinding(SystemCommands.RestoreWindowCommand, (_, __) => { SystemCommands.RestoreWindow(this); }));
        SizeToContent = SizeToContent.WidthAndHeight;
        ResizeMode = ResizeMode.NoResize;

    }

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);
        if (SizeToContent == SizeToContent.WidthAndHeight && WindowChrome.GetWindowChrome(this) != null)
        {
            InvalidateMeasure();
        }
    }
}

(2)样式文件CustomDialogWindow.xaml

    <Style TargetType="{x:Type ctrls:CustomDialogWindow}">
        <Setter Property="Foreground"
                Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
        <Setter Property="Background" Value="White" />
        <Setter Property="BorderBrush" Value="#FF0874AA" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="IsTabStop" Value="False" />
        <Setter Property="ResizeMode" Value="CanResizeWithGrip" />
        <Setter Property="UseLayoutRounding" Value="True" />
        <Setter Property="TextOptions.TextFormattingMode" Value="Display" />
        <Setter Property="WindowStyle" Value="SingleBorderWindow"/>
        <Setter Property="WindowChrome.WindowChrome">
            <Setter.Value>
                <WindowChrome CornerRadius="0"
                              GlassFrameThickness="1"
                              UseAeroCaptionButtons="False"
                              NonClientFrameEdges="None" />
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ctrls:CustomDialogWindow}">
                    <Border BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Background="{TemplateBinding Background}"
                            x:Name="WindowBorder">
                        <Grid x:Name="LayoutRoot">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="*" />
                            </Grid.RowDefinitions>
                            <Grid x:Name="PART_WindowTitleGrid"
                                  Grid.Row="0"
                                  Height="26.4"
                                  Background="{TemplateBinding BorderBrush}">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="Auto" />
                                </Grid.ColumnDefinitions>
                                <StackPanel Orientation="Horizontal">
                                    
                                    <Button VerticalAlignment="Center"
                                            Margin="7,0,5,0"
                                            Content="{TemplateBinding Icon}"
                                            Height="{x:Static SystemParameters.SmallIconHeight}"
                                            Width="{x:Static SystemParameters.SmallIconWidth}"
                                            WindowChrome.IsHitTestVisibleInChrome="True"
                                            IsTabStop="False">
                                        <Button.Template>
                                            <ControlTemplate TargetType="{x:Type Button}">
                                                <Image Source="{TemplateBinding Content}" />
                                            </ControlTemplate>
                                        </Button.Template>
                                        <i:Interaction.Triggers>
                                            <i:EventTrigger EventName="Click">
                                                <i:InvokeCommandAction Command="{x:Static SystemCommands.ShowSystemMenuCommand}" />
                                            </i:EventTrigger>
                                            <i:EventTrigger EventName="MouseDoubleClick">
                                                <i:InvokeCommandAction Command="{x:Static SystemCommands.CloseWindowCommand}" />
                                            </i:EventTrigger>
                                        </i:Interaction.Triggers>
                                    </Button>
                                    <ContentControl IsTabStop="False"
                                                    Foreground="White"
                                                    HorizontalAlignment="Center"
                                                    VerticalAlignment="Center"
                                                    FontSize="{DynamicResource {x:Static SystemFonts.CaptionFontSize}}"
                                                    Content="{TemplateBinding Title}" />
                                </StackPanel>
                                <StackPanel x:Name="WindowCommandButtonsStackPanel"
                                            Grid.Column="1"
                                            HorizontalAlignment="Right"
                                            VerticalAlignment="Stretch"
                                            Background="Transparent"
                                            Orientation="Horizontal"
                                            WindowChrome.IsHitTestVisibleInChrome="True"
                                            Margin="0,-1,-1,0">
                                    <Button x:Name="Minimize"
                                            ToolTip="Minimize"
                                            WindowChrome.IsHitTestVisibleInChrome="True"
                                            Command="{Binding Source={x:Static SystemCommands.MinimizeWindowCommand}}"
                                            ContentTemplate="{StaticResource MinimizeWhite}"
                                            Style="{StaticResource CaptionButtonStyle}"
                                            IsTabStop="False" />
                                    <Grid Margin="1,0,1,0">
                                        <Button x:Name="Restore"
                                                ToolTip="Restore"
                                                WindowChrome.IsHitTestVisibleInChrome="True"
                                                Command="{Binding Source={x:Static SystemCommands.RestoreWindowCommand}}"
                                                ContentTemplate="{StaticResource RestoreWhite}"
                                                Style="{StaticResource CaptionButtonStyle}"
                                                Visibility="Collapsed"
                                                IsTabStop="False" />
                                        <Button x:Name="Maximize"
                                                ToolTip="Maximize"
                                                WindowChrome.IsHitTestVisibleInChrome="True"
                                                Command="{Binding Source={x:Static SystemCommands.MaximizeWindowCommand}}"
                                                ContentTemplate="{StaticResource MaximizeWhite}"
                                                Style="{StaticResource CaptionButtonStyle}"
                                                IsTabStop="False" />
                                    </Grid>
                                    <Button x:Name="Close"
                                            ToolTip="Close"
                                            Background="Red"
                                            WindowChrome.IsHitTestVisibleInChrome="True"
                                            Command="{Binding Source={x:Static SystemCommands.CloseWindowCommand}}"
                                            ContentTemplate="{StaticResource CloseWhite}"
                                            Style="{StaticResource CaptionButtonStyle}"
                                            IsTabStop="False" />
                                </StackPanel>
                            </Grid>
                            <AdornerDecorator Grid.Row="1"
                                              KeyboardNavigation.IsTabStop="False">
                                <ContentPresenter Content="{TemplateBinding Content}" 
                                                  x:Name="MainContentPresenter" 
                                                  KeyboardNavigation.TabNavigation="Cycle" />
                            </AdornerDecorator>
                            <ResizeGrip x:Name="ResizeGrip"
                                        HorizontalAlignment="Right"
                                        VerticalAlignment="Bottom"
                                        Grid.Row="1"
                                        IsTabStop="False"
                                        Visibility="Hidden"
                                        WindowChrome.ResizeGripDirection="BottomRight" />
                        </Grid>
                    </Border>


                    <ControlTemplate.Triggers>
                        <Trigger Property="IsActive" Value="False">
                            <Setter Property="BorderBrush" Value="#FF6F7785" />
                        </Trigger>
                        <Trigger Property="WindowState" Value="Maximized">
                            <Setter TargetName="Maximize" Property="Visibility" Value="Collapsed" />
                            <Setter TargetName="Restore" Property="Visibility" Value="Visible" />
                            <Setter TargetName="LayoutRoot" Property="Margin" Value="7" />
                        </Trigger>
                        <Trigger Property="WindowState" Value="Normal">
                            <Setter TargetName="Maximize" Property="Visibility" Value="Visible" />
                            <Setter TargetName="Restore" Property="Visibility" Value="Collapsed" />
                        </Trigger>
                        <Trigger Property="ResizeMode" Value="NoResize">
                            <Setter TargetName="Minimize" Property="Visibility" Value="Collapsed" />
                            <Setter TargetName="Maximize" Property="Visibility" Value="Collapsed" />
                            <Setter TargetName="Restore" Property="Visibility" Value="Collapsed" />
                        </Trigger>

                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="ResizeMode" Value="CanResizeWithGrip" />
                                <Condition Property="WindowState" Value="Normal" />
                            </MultiTrigger.Conditions>
                            <Setter TargetName="ResizeGrip" Property="Visibility" Value="Visible" />
                        </MultiTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

2. 定义对话窗View和ViewModel

(1)DialogView

<UserControl x:Class="CustomDialogWindow.Views.DialogView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:CustomDialogWindow.Views"
             mc:Ignorable="d" Width="450" Height="300" Background="White">
    <Grid>
        <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="30" Text="这是一个Prism对话框"></TextBlock>
    </Grid>
</UserControl>

(2)DialogViewModel

public class DialogViewModel : BindableBase, IDialogAware
{
    public event Action<IDialogResult> RequestClose;
    #region Commands
    public DelegateCommand<string> ExcuteCommand { get; set; }
    #endregion
    private string title = "Title";

    public string Title
    {
        get { return title; }
        set { title = value; RaisePropertyChanged(); }
    }

    public DialogViewModel()
    {
        ExcuteCommand = new DelegateCommand<string>(Excute);
    }

    private void Excute(string name)
    {
        if ("YES".Equals(name))
        {
            RequestClose.Invoke(new DialogResult(ButtonResult.Yes));
        }
        else if ("Cancel".Equals(name))
        {
            RequestClose.Invoke(new DialogResult(ButtonResult.Cancel));
        }
    }

    public bool CanCloseDialog()
    {
        return true;
    }

    public void OnDialogClosed()
    {
    }
    
    public void OnDialogOpened(IDialogParameters parameters)
    {
        if (parameters.ContainsKey("Title"))
        {
            this.Title = parameters.GetValue<string>("Title");
        }
    }
}

3.定义MainWindow对应的ViewModel

public class MainWindowViewModel : BindableBase
{
    #region commands
    public DelegateCommand OpenCustomDialogCommand { get; set; }
    public DelegateCommand OpenDefalutDialogCommand { get; set; }
    #endregion

    #region Fields
    private IContainerProvider container;
    #endregion


    #region Constructor
    public MainWindowViewModel(IContainerProvider containerProvider)
    {
        container = containerProvider; 
        OpenCustomDialogCommand = new DelegateCommand(OpenCustomDialog);
        OpenDefalutDialogCommand = new DelegateCommand(OpenDefalutDialog);
    }

    private void OpenDefalutDialog()
    {
        IDialogService dialogService = container.Resolve<IDialogService>();
        IDialogParameters parameters = new DialogParameters();
        parameters.Add("Title", "DefaultDialogWindow");
        dialogService.ShowDialog("DialogView", parameters, null);

    }

    private void OpenCustomDialog()
    {
        IDialogService dialogService = container.Resolve<IDialogService>();
        IDialogParameters parameters = new DialogParameters();
        parameters.Add("Title", "CustomDialogWindow");
        dialogService.ShowDialog("DialogView", parameters, null, "CustomDialogWindow");
    }
    #endregion
}

4. 注册DialogWindow、View、ViewModel

/// <summary>
/// App.xaml 的交互逻辑
/// </summary>
public partial class App : PrismApplication
{
    protected override Window CreateShell()
    {
        return Container.Resolve<MainWindow>();
    }

    protected override void RegisterTypes(IContainerRegistry containerRegistry)
    {
        containerRegistry.RegisterDialogWindow<Controls.Windows.CustomDialogWindow>("CustomDialogWindow");
        containerRegistry.RegisterForNavigation<MainWindow, MainWindowViewModel>();
        containerRegistry.RegisterDialog<DialogView, DialogViewModel>("DialogView");
    }
}

5.运行效果

(1)自定义对话框窗体效果:

(2)默认对话框窗体效果