WPF MVVM框架 - Prism IDialogService 对话服务

232

在 WPF Prism 框架中,IDialogService 是一种用于实现对话框交互的服务,遵循 MVVM 模式,允许在 ViewModel 中管理对话框逻辑而无需直接操作视图。

基本概念

解耦性: 通过依赖注入实现 ViewModel 与对话框视图的解耦。

对话框类型: 支持模态和非模态对话框。

生命周期管理: 自动处理对话框的创建、显示和销毁

创建对话框 View

<UserControl x:Class="Prism_Base.Views.SwitchAccountDialogControl"
             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:Prism_Base.Views"
             mc:Ignorable="d" 
             d:DesignHeight="150" d:DesignWidth="300" Background="White">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="15"/>
        </Grid.RowDefinitions>
        <TextBlock Text="当前账号会登出,确定切换账号?" VerticalAlignment="Center" HorizontalAlignment="Center"/>
        <StackPanel Grid.Row="1" Orientation="Horizontal"  HorizontalAlignment="Center">
            <Button Content="确定" Width="100" Margin="4" Command="{Binding confirmCommand}"/>
            <Button Content="取消" Width="100" Margin="4" Command="{Binding cancelCommand}"/>
        </StackPanel>
    </Grid>
</UserControl>

创建对话框 ViewModel

    public class SwitchAccountDialogControlViewModel : BindableBase, IDialogAware
    {
        public DelegateCommand confirmCommand { get; private set; }
        public DelegateCommand cancelCommand { get; private set; }
        public DialogResult dialogResult { get; private set; }

        public SwitchAccountDialogControlViewModel()
        {
            confirmCommand = new DelegateCommand(Confirm);
            cancelCommand = new DelegateCommand(OnDialogClosed);
        }

        public DialogCloseListener RequestClose { get; }

        public bool CanCloseDialog()
        {
            return true;
        }

        public void OnDialogClosed()
        {
            RequestClose.Invoke(dialogResult);
        }

        public void OnDialogOpened(IDialogParameters parameters)
        {
            if (parameters.ContainsKey("param1"))
            {
                var param1 = parameters["param1"];
            }
        }

        public void Confirm()
        {
            dialogResult = new DialogResult(ButtonResult.OK);
            var parameters = new DialogParameters();
            parameters.Add("result", "ok");
            dialogResult.Parameters = parameters;

            OnDialogClosed();
        }

        public void cancel()
        {
            dialogResult = new DialogResult(ButtonResult.No);
            var parameters = new DialogParameters();
            parameters.Add("result", "ok");
            dialogResult.Parameters = parameters;

            OnDialogClosed();
        }
    }

注册对话框服务

在 App.xaml.cs 中的 RegisterTypes 方法内注册对话服务

public partial class App : PrismApplication
{
    protected override Window CreateShell()
    {
        return Container.Resolve<MainWindow>();
    }

    protected override void RegisterTypes(IContainerRegistry containerRegistry)
    {
        containerRegistry.RegisterForNavigation<MainWindow, MainWindowViewModel>();
        containerRegistry.RegisterForNavigation<CustomerManagerControl, CustomerManagerControlViewModel>();
        containerRegistry.RegisterForNavigation<SkuManagerControl, SkuManagerControlViewModel>();
        containerRegistry.RegisterForNavigation<SystemManagerControl, SystemManagerControlViewModel>();
        
        // 注册对话服务
        containerRegistry.RegisterDialog<SwitchAccountDialogControl, SwitchAccountDialogControlViewModel>();
    }
}

打开对话框

注入IDialogService接口,调用 Show 方法打开对话框,传递参数,编写回调事件

  public class MainWindowViewModel : BindableBase
  {
      public DelegateCommand<string> NavigateCommand { get; private set; }
      public DelegateCommand SwitchAccountCommand { get; private set; }

      private readonly IRegionManager _regionManager;
      private readonly IDialogService _dialogService;

      public MainWindowViewModel(IRegionManager regionManager, IDialogService dialogService)
      {
          NavigateCommand = new DelegateCommand<string>(Navigate);
          SwitchAccountCommand = new DelegateCommand(SwitchAccount);

          _regionManager = regionManager;
          _dialogService = dialogService;
      }

      public void Navigate(string viewName)
      {
          _regionManager.RequestNavigate("ContentRegion", viewName);
      }

      public void SwitchAccount()
      {
          var parameters = new DialogParameters();
          parameters.Add("param1", "value1");

          _dialogService.Show("SwitchAccountDialogControl", parameters, result =>
          {
              if (result.Result == ButtonResult.OK)
              {
                  // 确定
                  Application.Current.Shutdown();
              }
              else
              {
                  // 取消
              }
          });
      }
  }

常见问题排查

对话框未显示:

  • 确保已正确注册对话框 RegisterDialog<MyDialog, MyDialogViewModel>()。

  • 检查对话框名称是否匹配 ShowDialog("MyDialog")。

参数未接收:

  • 检查发送和接收的键名是否一致。

  • 确认 ViewModel 实现了 IDialogAware 并在 OnDialogOpened 中处理参数。

对话框关闭无响应:

  • 确保调用了 RequestClose.Invoke(result)。

  • 检查 ButtonResult 是否正确设置(如 ButtonResult.OK)。