WPF Prsim(一)Region
WPF Prism(二)Module
WPF Prism(三)ViewModelLocator
WPF Prism(四)MVVM
WPF Prism(五)Navigation
WPF Prism(六)Dialog

一、什么是Dialog

对话框实际上是我们应用程序经常用到得一个功能,类如:Show、Show Dialog。可以弹出一个我们指定得窗口,仅此而已那么在Prism当中,Dialog指的什么?

Prism提供了一组对话服务,封装了常用的对话框组件的功能,例如:

  • RegisterDialog/IDialogService (注册对话及使用对话)
  • 打开对话框传递参数/关闭对话框返回参数
  • 回调通知对话结果

二、创建Dialog

Dialog其实也是一组用户控件,我们可以创建一个子模块,然后不需要继承IModule,继承了也没有关系,只要不加载该子模块就行,这样我们可以把他当作对话框或者子模块使用,而不需要改动太多代码。值得一提的是,默认情况下这个控件会嵌入到窗体中弹出,所以我们可以定义弹出窗体的一些属性:

    <prism:Dialog.WindowStyle>
        <Style TargetType="Window">
            <Setter Property="prism:Dialog.WindowStartupLocation" Value="CenterOwner" />
            <Setter Property="WindowChrome.WindowChrome">
                <Setter.Value>
                    <WindowChrome CaptionHeight="0" ResizeBorderThickness="5" />
                </Setter.Value>
            </Setter>
            <Setter Property="WindowStyle" Value="None" />
            <Setter Property="AllowDrop" Value="True" />
            <Setter Property="BorderThickness" Value="0" />
            <Setter Property="ShowInTaskbar" Value="False" />
            <Setter Property="SizeToContent" Value="WidthAndHeight" />
        </Style>
    </prism:Dialog.WindowStyle>

然后我们Dialog的ViewModel需要继承接口IDialogAware,这个接口我们在后面再细说。

三、注册Dialog

我们在App类的重写函数中注册对话框服务:

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterDialog<DialogA.Views.DialogA>();
            containerRegistry.RegisterDialog<DialogA.Views.DialogA>("DialogA");
            containerRegistry.RegisterDialog<DialogA.Views.DialogA, DialogA.ViewModels.DialogAViewModel>();
        }

如果没有传递字符串参数,则DialogName默认为类名(View的类名)。也可以在注册的使用将View和ViewModel进行绑定,不过一般就是View的xaml代码中使用

 prism:ViewModelLocator.AutoWireViewModel="True"

进行关联。

四、调用Dialog

要调用Dialog,我们需要拿到IDialogService接口的实现,而这个实现容器中已经注册过了,我们只需要在构造函数中注入即可。

    private IDialogService dialog;
    public MainWindowViewModel(IRegionManager regionManager,IDialogService dialogService)
    {
        this.region = regionManager;
        this.dialog = dialogService;
    }

然后调用这两个方法中的一个就可以打开对话框:

        this.dialog.ShowDialog("DialogA");//模态对话框:父窗体禁止使用
        this.dialog.Show("DialogA");//非模态对话框:父窗体可以继续使用

五、IDialogService接口及其拓展

public interface IDialogService
{
    void Show(string name, IDialogParameters parameters, Action<IDialogResult> callback);
    void Show(string name, IDialogParameters parameters, Action<IDialogResult> callback, string windowName);
    void ShowDialog(string name, IDialogParameters parameters, Action<IDialogResult> callback);
    void ShowDialog(string name, IDialogParameters parameters, Action<IDialogResult> callback, string windowName);
}
//
// 摘要:
//     Extensions for the IDialogService
public static class IDialogServiceExtensions
{
    public static void Show(this IDialogService dialogService, string name);
    public static void Show(this IDialogService dialogService, string name, Action<IDialogResult> callback);
    public static void ShowDialog(this IDialogService dialogService, string name);
    public static void ShowDialog(this IDialogService dialogService, string name, Action<IDialogResult> callback);
}

接口的实现中,最多有四个参数:

  • name:指的是Dialog的name,由注册的时候指定,没有指定的时候默认为View类的类名
  • parameters:传递给对话框的参数
  • callback:对话框被关闭时的回调函数
  • windowName:注册对话框的父窗体名称

拓展方法中最多有两个参数,其中省略了parameters和windowName。

        private void OpenDialog()
        {
            IDialogParameters parameters = new DialogParameters();
            parameters.Add("param1", "Hello");

            this.dialog.ShowDialog("DialogA", parameters, DialogCallback);
        }

        private void DialogCallback(IDialogResult result)
        {
            //对话框关闭之后的回调函数,可以在这解析结果。
            ButtonResult result1 = result.Result;

            var param = result.Parameters.GetValue<string>("param1");
        }

六、IDialogAware

这个接口一般由ViewModel来继承。

//
// 摘要:
//     Interface that provides dialog functions and events to ViewModels.
public interface IDialogAware
{
    //
    // 摘要:
    //     The title of the dialog that will show in the window title bar.
    string Title { get; }

    //
    // 摘要:
    //     Instructs the Prism.Services.Dialogs.IDialogWindow to close the dialog.
    event Action<IDialogResult> RequestClose;

    //
    // 摘要:
    //     Determines if the dialog can be closed.
    //
    // 返回结果:
    //     If true the dialog can be closed. If false the dialog will not close.
    bool CanCloseDialog();
    //
    // 摘要:
    //     Called when the dialog is closed.
    void OnDialogClosed();
    //
    // 摘要:
    //     Called when the dialog is opened.
    //
    // 参数:
    //   parameters:
    //     The parameters passed to the dialog.
    void OnDialogOpened(IDialogParameters parameters);
}
  • Title:表示对话框窗体的标题。(打开对话框的时候,其实还是将该用户空间装载到了一个窗体中)
  • Action RequestClose:触发这个事件去关闭对话框,这个事件的订阅就是前面说到的当对话框关闭后的回调函数。
  • CanCloseDialog():如果返回true,则表示可以关闭对话框,否则不可以关闭对话框。(这时按钮不会灰调,但是点击无效。即使触发RequestClose也会无效)
  • OnDialogClosed:当对话框被关闭的时候触发这个方法(无论是点击关闭按钮还是触发事件)
  • OnDialogOpened(IDialogParameters parameters):当对话框被打开的时候触发这个方法,并且传递对话框参数进来。
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>

    <TextBox
        Grid.Row="0"
        Height="30"
        Margin="20"
        HorizontalAlignment="Center"
        VerticalAlignment="Center"
        VerticalContentAlignment="Center"
        Text="{Binding Message}" />

    <StackPanel Grid.Row="1" Orientation="Horizontal">
        <StackPanel.Resources>
            <Style TargetType="Button">
                <Setter Property="Margin" Value="20" />
                <Setter Property="Height" Value="30" />
                <Setter Property="Width" Value="80" />
            </Style>
        </StackPanel.Resources>
        <Button Command="{Binding ClickYesCmd}" Content="Yes" />
        <Button Command="{Binding ClickNoCmd}" Content="NO" />
    </StackPanel>
</Grid>
    private void ClickNo()
    {
        //点击No按钮的时候关闭对话框,并且传递对话框结果(结果中还可以带参数)
        RequestClose?.Invoke(new DialogResult(ButtonResult.Cancel));
    }

    private void ClickYes()
    {
        //点击Yes按钮的时候关闭对话框,并且传递对话框结果(结果中还可以带参数)
        IDialogParameters parameters = new DialogParameters();
        parameters.Add("param1", "Hello Baby");
        RequestClose?.Invoke(new DialogResult(ButtonResult.OK, parameters));
    }

    public bool CanCloseDialog()
    {
        //始终允许关闭对话框
        return true;
    }

    public void OnDialogClosed()
    {
        //当对话框关闭的时候啥也不干
    }

    public void OnDialogOpened(IDialogParameters parameters)
    {
        //打开对话框的时候解析传递进来的参数
        Message = parameters.GetValue<string>("param1");
    }
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐