.NET Core 3 WPF MVVM框架 Prism系列之對話框服務

 本文將介紹如何在.NET Core3環境下使用MVVM框架Prism的對話框服務,這也是prism系列的最後一篇完結文章,下面是Prism系列文章的索引:
.NET Core 3 WPF MVVM框架 Prism系列之文章索引html

一.對話框服務

在Prism中,經過一個IDialogAware接口來實現對話框服務:git

public interface IDialogAware
{
    bool CanCloseDialog();
    void OnDialogClosed();
    void OnDialogOpened(IDialogParameters parameters);
    string Title { get; set; }
    event Action<IDialogResult> RequestClose;
}
  • CanCloseDialog()函數是決定窗體是否關閉
  • OnDialogClosed()函數是窗體關閉時觸發,觸發條件取決於CanCloseDialog()函數
  • OnDialogOpened()函數時窗體打開時觸發,比窗體Loaded事件早觸發
  • Title爲窗體的標題
  • RequestClose爲關閉事件,可由此控制窗體的關閉

1.建立對話框的View和ViewModel

AlertDialog.xaml:github

<UserControl x:Class="PrismMetroSample.Shell.Views.Dialogs.AlertDialog"
             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:PrismMetroSample.Shell.Views.Dialogs"
             mc:Ignorable="d"  
             xmlns:prism="http://prismlibrary.com/"
             Width="350" Height="120" prism:ViewModelLocator.AutoWireViewModel="True">
    <Grid  Margin="5">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid Margin="0,0,0,10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="70"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Image Source="pack://application:,,,/PrismMetroSample.Infrastructure;Component/Assets/Photos/alter.png" Height="40" UseLayoutRounding="True" RenderOptions.BitmapScalingMode="HighQuality"/>
            <TextBlock  Grid.Column="1" Text="{Binding Message}" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Row="0" TextWrapping="Wrap"  FontSize="15" FontFamily="Open Sans"/>
        </Grid>
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Button Margin="5"  Foreground="White"  FontSize="12" Background="#5cb85c" Command="{Binding CloseDialogCommand}" CommandParameter="true" Content="Yes" Width="64" Height="28" HorizontalAlignment="Right" Grid.Row="1"/>
            <Button Grid.Column="1" Margin="5"  Foreground="White"  FontSize="12" Background="#d9534f" Command="{Binding CloseDialogCommand}" CommandParameter="false" Content="No" Width="64" Height="28" HorizontalAlignment="Left" Grid.Row="1"/>
        </Grid>
       
    </Grid>
</UserControl>

AlertDialogViewModel.cs:express

public class AlertDialogViewModel : BindableBase, IDialogAware
{
    private DelegateCommand<string> _closeDialogCommand;
    public DelegateCommand<string> CloseDialogCommand =>
        _closeDialogCommand ?? (_closeDialogCommand = new DelegateCommand<string>(ExecuteCloseDialogCommand));

    void ExecuteCloseDialogCommand(string parameter)
    {
        ButtonResult result = ButtonResult.None;
        if (parameter?.ToLower() == "true")
            result = ButtonResult.Yes;
        else if (parameter?.ToLower() == "false")
            result = ButtonResult.No;
         RaiseRequestClose(new DialogResult(result));
     }

     //觸發窗體關閉事件
     public virtual void RaiseRequestClose(IDialogResult dialogResult)
     {
         RequestClose?.Invoke(dialogResult);
     }

     private string _message;
     public string Message
     {
         get { return _message; }
         set { SetProperty(ref _message, value); }
     }

     private string _title = "Notification";
     public string Title
     {
         get { return _title; }
         set { SetProperty(ref _title, value); }
     }

     public event Action<IDialogResult> RequestClose;

     public bool CanCloseDialog()
     {
         return true;
     }

     public void OnDialogClosed()
     {
            
     }

     public void OnDialogOpened(IDialogParameters parameters)
     {
         Message = parameters.GetValue<string>("message");
     }
 }

2.註冊對話框

App.cs:c#

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
     containerRegistry.RegisterDialog<AlertDialog, AlertDialogViewModel>();
}

還能夠註冊時起名字:app

containerRegistry.RegisterDialog<AlertDialog, AlertDialogViewModel>(「alertDialog」);

3.使用對話框服務

CreateAccountViewModel.cs(修改部分):框架

public CreateAccountViewModel(IRegionManager regionManager, IDialogService dialogService)
{
     _regionManager = regionManager;
     _dialogService = dialogService;
}

 public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
 {
     if (!string.IsNullOrEmpty(RegisteredLoginId) && this.IsUseRequest)
     {
          _dialogService.ShowDialog("AlertDialog", new DialogParameters($"message={"是否須要用當前註冊的用戶登陸?"}"), r =>
           {
                 if (r.Result == ButtonResult.Yes)
                     navigationContext.Parameters.Add("loginId", RegisteredLoginId);
           });
      }
      continuationCallback(true);

 }

效果以下:ide

咱們是經過調用IDialogService接口的ShowDialog函數來調用,下面是該接口的定義:函數

public interface IDialogService : Object
{
    Void Show(String name, IDialogParameters parameters, Action<IDialogResult> callback);
    Void ShowDialog(String name, IDialogParameters parameters, Action<IDialogResult> callback);
    
 }

咱們能夠發現show和ShowDialog函數都是同樣形參,無非就是使用場景不同this

  • name:所要調用對話框view的名字,當註冊別名時,只能使用別名來調用
  • parameters:IDialogParameters接口類型參數,傳入的提示消息,一般是$"message={xxxx}"格式,而後再ViewModel的OnDialogOpened函數經過IDialogParameters接口的GetValue函數來獲取
  • callback:用於傳入無返回值回調函數

二.自定義對話框窗體

 咱們在上述能夠看到,對話框的窗體時一個WPF自帶的窗體,可是當咱們要用本身自定義窗體,例如,去掉window的Icon,保留最大化,最小化和關閉,或者使用一些第三方的窗體控件,prism支持經過註冊一個對話框窗體,而後經過再不一樣對話框的View指定其對話框窗體的style,則能夠很靈活的實現不同的對話框,下面讓咱們來看看如何操做:

1.註冊自定義對話框窗體

新建一個窗體,DialogWindow.xaml:

<Window x:Class="PrismMetroSample.Shell.Views.Dialogs.DialogWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:PrismMetroSample.Shell.Views.Dialogs"
        mc:Ignorable="d"  
        xmlns:prism="http://prismlibrary.com/"
         >
    <Grid>
        
    </Grid>
</Window>

DialogWindow.xaml.cs:

public partial class DialogWindow : Window, IDialogWindow
{
    public DialogWindow()
    {
        InitializeComponent();
    }

    protected override void OnSourceInitialized(EventArgs e)
    {
        WindowHelp.RemoveIcon(this);//使用win32函數去除Window的Icon部分
    }

    public IDialogResult Result { get; set; }
}

App.cs:

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
     containerRegistry.RegisterDialogWindow<DialogWindow>();//註冊自定義對話框窗體
}

2.自定義對話框窗體Style

AlertDialog.xaml:

<prism:Dialog.WindowStyle>
     <Style TargetType="Window">
          <Setter Property="prism:Dialog.WindowStartupLocation" Value="CenterScreen" />
          <Setter Property="ShowInTaskbar" Value="False"/>
          <Setter Property="SizeToContent" Value="WidthAndHeight"/>
     </Style>
 </prism:Dialog.WindowStyle>

效果以下:

如何咱們要將窗體樣式所有去掉,改動AlertDialog.xaml:

<prism:Dialog.WindowStyle>
     <Style TargetType="Window">
          <Setter Property="prism:Dialog.WindowStartupLocation" Value="CenterScreen" />
          <Setter Property="ShowInTaskbar" Value="False"/>
          <Setter Property="SizeToContent" Value="WidthAndHeight"/>
          <Setter Property="WindowStyle" Value="None"/>
     </Style>
 </prism:Dialog.WindowStyle>

那麼就變成了下面這樣:

最終,咱們的最後效果爲這樣:

三.小結

 經過Prism的對話框服務,咱們能夠很好的經過一個IDialogService接口來統一管理對話框的彈出邏輯,並且可使用依賴注入的模式,若是換成以前要定義一些自定義的對話框,那麼也要強依賴View部分,並且能夠經過自定義不一樣對話框的窗體樣式,達到必定的靈活性(例如最終效果演示,用了兩個不一樣的對話框樣式),至此, .NET Core3.x Prism系列文章已經所有寫完

四.源碼

 最後,附上整個demo的源代碼:PrismDemo源碼

相關文章
相關標籤/搜索