对话框服务
TODO: Intro
创建对话框视图
您的对话框视图是一个简单的UserControl,您可以按照自己的想法设计它。唯一的要求是它的DataContext属性需要绑定了一个实现IDialogAware
接口的ViewModel。您最好的解决方法是使用ViewModelLocator
实现此需求。
<UserControl x:Class="HelloWorld.Dialogs.NotificationDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
Width="300" Height="150">
<Grid x:Name="LayoutRoot" Margin="5">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding Message}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="0" TextWrapping="Wrap" />
<Button Command="{Binding CloseDialogCommand}" CommandParameter="true" Content="OK" Width="75" Height="25" HorizontalAlignment="Right" Margin="0,10,0,0" Grid.Row="1" IsDefault="True" />
</Grid>
</UserControl>
创建您的对话框视图模型
接下来,您需要一个实现IDialogAware
的ViewModel,其定义如下
public interface IDialogAware
{
bool CanCloseDialog();
void OnDialogClosed();
void OnDialogOpened(IDialogParameters parameters);
string Title { get; set; }
event Action<IDialogResult> RequestClose;
}
下面是一个IDialogAware
视图模型的简单示例。
public class NotificationDialogViewModel : BindableBase, IDialogAware
{
private DelegateCommand<string> _closeDialogCommand;
public DelegateCommand<string> CloseDialogCommand =>
_closeDialogCommand ?? (_closeDialogCommand = new DelegateCommand<string>(CloseDialog));
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;
protected virtual void CloseDialog(string parameter)
{
ButtonResult result = ButtonResult.None;
if (parameter?.ToLower() == "true")
result = ButtonResult.OK;
else if (parameter?.ToLower() == "false")
result = ButtonResult.Cancel;
RaiseRequestClose(new DialogResult(result));
}
public virtual void RaiseRequestClose(IDialogResult dialogResult)
{
RequestClose?.Invoke(dialogResult);
}
public virtual bool CanCloseDialog()
{
return true;
}
public virtual void OnDialogClosed()
{
}
public virtual void OnDialogOpened(IDialogParameters parameters)
{
Message = parameters.GetValue<string>("message");
}
}
注册Dialog
要注册一个对话框,您必须有一个View(UserControl)和一个相应的ViewModel(它必须实现IDialogAware
)。在RegisterTypes
方法中,只需像注册其他服务一样使用IContainterRegistery.RegisterDialog
注册你的对话框服务。
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterDialog<NotificationDialog, NotificationDialogViewModel>();
}
或者,您可以为您的对话框提供一个自定义名称。
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterDialog<NotificationDialog, NotificationDialogViewModel>("myDialog");
}
使用对话框服务
要使用对话框服务,您只需在VM ctor中调用该服务。
public MainWindowViewModel(IDialogService dialogService)
{
_dialogService = dialogService;
}
然后调用Show
或ShowDialog
,并提供对话框的名称以及对话框所需要的参数,最后通过回调处理结果。
private void ShowDialog()
{
var message = "This is a message that should be shown in the dialog.";
//using the dialog service as-is
_dialogService.ShowDialog("NotificationDialog", new DialogParameters($"message={message}"), r =>
{
if (r.Result == ButtonResult.None)
Title = "Result is None";
else if (r.Result == ButtonResult.OK)
Title = "Result is OK";
else if (r.Result == ButtonResult.Cancel)
Title = "Result is Cancel";
else
Title = "I Don't know what you did!?";
});
}
注册自定义对话框窗口
使用第三方控件(例如Infragistics)是很常见的。在这些情况下,您可能希望将承载对话框的标准WPF窗口控件替换为自定义窗口类,例如Infragistics XamRibbonWindow控件。
在这种情况下,您只需创建自己的自定义窗口,并实现IDialogWindow
接口:
public partial class MyRibbonWindow: XamRibbonWindow, IDialogWindow
{
public IDialogResult Result { get; set; }
….
}
然后使用IContainerRegistry
注册您的对话框窗口。
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterDialogWindow<MyRibbonWindow>();
}
如果您想将多个对话框窗口用作对话框宿主,则可以通过为窗口指定一个名称来向容器注册多个对话框窗口。
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterDialogWindow<NotificationWindow>("notifyWindow");
}
[!注意] 为了按名称使用对话框窗口,您必须在
IDialogService.Show
或IDialogService.ShowDialog
方法中提供对话框窗口名称,如下所示:
_dialogService.ShowDialog("DialogName", dialogParameters), r =>
{ ... }, "notifyWindow");
设置对话框窗口样式
你可以通过对话框控件上的附加属性来使用样式控制对话框窗口的属性
<prism:Dialog.WindowStyle>
<Style TargetType="Window">
<Setter Property="prism:Dialog.WindowStartupLocation" Value="CenterScreen" />
<Setter Property="ResizeMode" Value="NoResize"/>
<Setter Property="ShowInTaskbar" Value="False"/>
<Setter Property="SizeToContent" Value="WidthAndHeight"/>
</Style>
</prism:Dialog.WindowStyle>
简化应用程序对话框API
对话框API的目的是创建和显示对话框,而不是尝试和猜测所有对话框所需的参数类型。因此为了简化应用程序中的常见的对话框,指南将创建一个扩展方法来简化应用程序对话框。
例如:
public static class DialogServiceExtensions
{
public static void ShowNotification(this IDialogService dialogService, string message, Action<IDialogResult> callBack)
{
dialogService.ShowDialog("NotificationDialog", new DialogParameters($"message={message}"), callBack, "notificationWindow");
}
}
然后使用您专门为应用程序所创建的新改进API来调用通知。
_dialogService.ShowNotification(message, r =>
{
if (r.Result == ButtonResult.None)
Title = "Result is None";
else if (r.Result == ButtonResult.OK)
Title = "Result is OK";
else if (r.Result == ButtonResult.Cancel)
Title = "Result is Cancel";
else
Title = "I Don't know what you did!?";
});