(7/7).NET Core 3 WPF MVVM Framework Prism Series: Dialog Service

(7/7).NET Core 3 WPF MVVM Framework Prism Series: Dialog Service

How to use the dialog service of the MVVM framework Prism in .NET Core 3 environment, and this is the final article of the Prism series.

Last updated 6/11/2023 12:47 AM
RyzenAdorer
7 min read
Category
WPF
Topic
WPF MVVM Framework Prism Series
Tags
.NET C# WPF Prism MVVM

This article is a reprint

Original author: RyzenAdorer

Original title: .NET Core 3 WPF MVVM Framework Prism Series: Dialog Service

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

This article will introduce how to use the dialog service of the MVVM framework Prism in a .NET Core 3 environment. This is also the final article of the Prism series. Below is the index of the Prism series:

.NET Core 3 WPF MVVM Framework Prism Series: Article Index

1. Dialog Service

In Prism, dialog services are implemented through an IDialogAware interface:

public interface IDialogAware
{
    bool CanCloseDialog();
    void OnDialogClosed();
    void OnDialogOpened(IDialogParameters parameters);
    string Title { get; set; }
    event Action<IDialogResult> RequestClose;
}
  • CanCloseDialog() determines whether the form can be closed.
  • OnDialogClosed() is triggered when the form closes, depending on the return value of CanCloseDialog().
  • OnDialogOpened() is triggered when the form opens, earlier than the form's Loaded event.
  • Title is the form's title.
  • RequestClose is the close event, through which the form's closure can be controlled.

2.1. Creating the Dialog's View and ViewModel

AlertDialog.xaml:

<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:

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));
     }

     // Trigger form close event
     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.2. Registering the Dialog

App.cs:

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
     containerRegistry.RegisterDialog<AlertDialog, AlertDialogViewModel>();
}
You can also register it with a name:

Copy
containerRegistry.RegisterDialog<AlertDialog, AlertDialogViewModel>("alertDialog");

2.3. Using the Dialog Service

CreateAccountViewModel.cs (modified portion):

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);

 }

Effect:

We call it by using the ShowDialog function of the IDialogService interface. Below is the definition of this interface:

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

 }

We can see that the Show and ShowDialog functions have the same parameters; the difference is just the usage scenario:

  • name: The name of the dialog view to call. When registered with an alias, only the alias can be used.
  • parameters: Parameters of type IDialogParameters, the message to pass. Usually in the format $"message={xxxx}", then retrieved in the ViewModel's OnDialogOpened function via the GetValue method of IDialogParameters.
  • callback: Used to pass a callback function with no return value.

2. Custom Dialog Window

In the above example, the dialog window is the default WPF window. But when we want to use a custom window — for example, removing the window icon, keeping only maximize, minimize, and close, or using third-party window controls — Prism supports registering a custom dialog window. Then, by specifying the dialog window's style for different dialog views, we can achieve flexible styling. Let's see how to do it:

2.1. Registering a Custom Dialog Window

Create a new window, 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); // Use Win32 function to remove the window icon
    }

    public IDialogResult Result { get; set; }
}

App.cs:

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
     containerRegistry.RegisterDialogWindow<DialogWindow>(); // Register custom dialog window
}

2.2. Custom Dialog Window 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>

Effect:

If we want to remove all window styles, modify 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>

Then it becomes like this:

Finally, the final effect is:

3. Summary

With Prism's dialog service, we can centrally manage the logic of opening dialogs through an IDialogService interface, and we can use dependency injection. Previously, if we wanted to define custom dialogs, we had to strongly depend on the View part. Now, by customizing the window style for different dialogs, we achieve a certain degree of flexibility (as seen in the final demo with two different dialog styles). This concludes the entire .NET Core 3.x Prism series.

4. Source Code

Finally, here is the source code for the entire demo: PrismDemo Source Code

Keep Exploring

Related Reading

More Articles