天天看點

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

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

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

.NET Core 3 WPF MVVM架構 Prism系列之文章索引

一.對話框服務#

在Prism中,通過一個IDialogAware接口來實作對話框服務:

Copy

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:

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>           

AlertDialogViewModel.cs:

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:

protected override void RegisterTypes(IContainerRegistry containerRegistry)

containerRegistry.RegisterDialog<AlertDialog, AlertDialogViewModel>();           

還可以注冊時起名字:

containerRegistry.RegisterDialog(“alertDialog”);

3.使用對話框服務#

CreateAccountViewModel.cs(修改部分):

public CreateAccountViewModel(IRegionManager regionManager, IDialogService dialogService)

_regionManager = regionManager;
 _dialogService = dialogService;           

public void ConfirmNavigationRequest(NavigationContext navigationContext, Action 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);
           

效果如下:

我們是通過調用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函數都是一樣形參,無非就是使用場景不一樣

name:所要調用對話框view的名字,當注冊别名時,隻能使用别名來調用

parameters:IDialogParameters接口類型參數,傳入的提示消息,通常是$"message={xxxx}"格式,然後再ViewModel的OnDialogOpened函數通過IDialogParameters接口的GetValue函數來擷取

callback:用于傳入無傳回值回調函數

二.自定義對話框窗體#

我們在上述可以看到,對話框的窗體時一個WPF自帶的窗體,但是當我們要用自己自定義窗體,例如,去掉window的Icon,保留最大化,最小化和關閉,或者使用一些第三方的窗體控件,prism支援通過注冊一個對話框窗體,然後通過再不同對話框的View指定其對話框窗體的style,則可以很靈活的實作不一樣的對話框,下面讓我們來看看如何操作:

1.注冊自定義對話框窗體#

建立一個窗體,DialogWindow.xaml:

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>           

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; }           
containerRegistry.RegisterDialogWindow<DialogWindow>();//注冊自定義對話框窗體           

2.自定義對話框窗體Style#

AlertDialog.xaml:

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

效果如下:

如何我們要将窗體樣式全部去掉,改動AlertDialog.xaml:

<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的對話框服務,我們可以很好的通過一個IDialogService接口來統一管理對話框的彈出邏輯,而且可以使用依賴注入的模式,如果換成之前要定義一些自定義的對話框,那麼也要強依賴View部分,而且可以通過自定義不同對話框的窗體樣式,達到一定的靈活性(例如最終效果示範,用了兩個不同的對話框樣式),至此, .NET Core3.x Prism系列文章已經全部寫完

四.源碼#

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

作者: RyzenAdorer

出處:

https://www.cnblogs.com/ryzen/p/12771986.html