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 ofCanCloseDialog().OnDialogOpened()is triggered when the form opens, earlier than the form'sLoadedevent.Titleis the form's title.RequestCloseis 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 typeIDialogParameters, the message to pass. Usually in the format$"message={xxxx}", then retrieved in the ViewModel'sOnDialogOpenedfunction via theGetValuemethod ofIDialogParameters.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