-
Notifications
You must be signed in to change notification settings - Fork 2
WPF: Dialog Manager
Dialog view is a simple UserControl that can be designed anyway you please. The only requirement it has a ViewModel that implements IDialogAware
set as it's DataContext.
The sample view DialogA.xaml
as shown below.
<UserControl x:Class="AppDialogs.Views.Dialogs.DialogA"
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"
mc:Ignorable="d"
Height="200"
Width="400">
<Grid>
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
TextWrapping="Wrap"
Text="Modal dialog A content">
</TextBlock>
</Grid>
</UserControl>
Next you need a ViewModel that implements IDialogAware
which is defined as follows
public interface IDialogAware
{
/// <summary>
/// The title of the dialog that will show in the hostWindow title bar.
/// </summary>
string Title { get; }
/// <summary>
/// Instructs the IDialogHostWindow to close the dialog.
/// </summary>
event Action<IDialogResult> RequestClose;
/// <summary>
/// Determines if the dialog can be closed.
/// </summary>
/// <returns>If <c>true</c> the dialog can be closed. If <c>false</c> the dialog will not close.</returns>
bool CanCloseDialog();
/// <summary>
/// Called when the dialog is closed.
/// </summary>
void OnDialogClosed();
/// <summary>
/// Called when the dialog is opened.
/// </summary>
/// <param name="parameters">The parameters passed to the dialog.</param>
void OnDialogOpened(IDialogParameters parameters);
}
The sample ViewModel for the view DialogA.xaml
public class DialogAViewModel : BindableBase, IDialogAware
{
public DialogAViewModel()
{
Title = "Dialog A";
}
public string Title { get; protected set;}
public event Action<IDialogResult> RequestClose;
protected virtual void CloseDialog(IDialogResult dialogResult = null)
{
RequestClose?.Invoke(dialogResult ?? new DialogResult());
}
public virtual bool CanCloseDialog() => true;
public virtual void OnDialogClosed() { }
public virtual void OnDialogOpened(IDialogParameters parameters) { }
}
Bind object of the ViewModel to the property DataContext
of the view. It is important to keep parameterless constructor because view objects will be instantiated internally using Activator.CreateInstance(viewType)
.
The sample code demonstrates how to bind ViewModel to dialog view.
// DialogA.xaml.cs file
public partial class DialogA : UserControl
{
// It is important to keep parameterless constructor of view object, if you use IoC container.
// This restriction applicable only for view objects.
public DialogA()
{
// Resolve ViewModel object from static instance of the container.
DataContext = App.Container.Resolve<DialogAViewModel>();
InitializeComponent();
}
}
Register instance of IDialogManager
as a singleton in the container then register all dialog views in the IDialogManager
.
The sample code shows how to register IDialogManager
and dialog views in application entry point class (App.xaml.cs
file) and used DryIoc container as a IoC container.
public partial class App : Application
{
// Static singleton instance of DryIoc container.
public static readonly IContainer Container = new Container();
/// <summary>
/// Application entry point.
/// </summary>
/// <param name="e">Args</param>
protected override void OnStartup(StartupEventArgs e)
{
// Register IDialogManager service as a singleton.
// Note: It's important to register as a singelton otherwise you will get different instance of managers.
Container.Register<IDialogManager, DialogManager>(Reuse.Singleton);
// Resolve singleton instance of the dialog manager from container.
Container.Resolve<IDialogManager>()
.RegisterDialog<DialogA>() // register all dialog views in the dialog manager.
.RegisterDialog<DialogB>()
.RegisterDialog<DialogC>();
// Resolve MainWindow from container then display main window.
Container.Resolve<MainWindow>().Show();
base.OnStartup(e);
}
}
NOTE: You must provide dialog name when you register dialogs in
IDialogManager.Register<>
. In above example, explicitly not specified dialog name because by default name of view type will be used implicitly as a dialog name. In case of the above example, view typesDialogA
,DialogB
andDialogC
used as a default dialog name such that "DialogA", "DialogB" and "DialogC".
Inject IDialogManager
to your view model constructor.
public MainWindowViewModel(IDialogManager dialogManager)
{
_dialogManager = dialogManager;
}
Then call either Show
or ShowDialog
providing the name of the dialog, any parameters your dialogs requires, and then handle the result via a call back.
private void ShowModalDialog()
{
var dialogParameters = new DialogParameters
{
{"paramKey1", "paramValue1"},
{"paramKey2", "paramValue2"},
{"paramKey3", "paramValue3"}
};
_dialogManager.ShowDialog("DialogA", dialogParameters);
}
You can control the properties of the DialogHostWindow
by using a style via an attatched property on the Dialog UserControl.
The sample code demonstrates how to make transparent background of the dialog host window.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="dialogHostStyle" TargetType="{x:Type Window}">
<Setter Property="WindowStyle" Value="None"></Setter>
<Setter Property="AllowsTransparency" Value="True"></Setter>
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Opacity="0.5" Color="Black"/>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Use your styles in dialog view.
<UserControl x:Class="AppDialogs.Views.Dialogs.DialogA"
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:attached="clr-namespace:MagicMvvm.Dialogs;assembly=MagicMvvm.Wpf"
attached:DialogHost.WindowStyle="{StaticResource dialogHostStyle}"
attached:DialogHost.MatchParentSize="True"
mc:Ignorable="d"
Height="200"
Width="400">
<Grid>
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
TextWrapping="Wrap"
Text="Modal dialog A content">
</TextBlock>
</Grid>
</UserControl>
Check out sample project where demonstrated all features of the Dialog Manager.