WPF Prsim(一)Region
WPF Prism(二)Module
WPF Prism(三)ViewModelLocator
WPF Prism(四)MVVM
WPF Prism(五)Navigation
WPF Prism(六)Dialog
对话框实际上是我们应用程序经常用到得一个功能,类如:Show、Show Dialog。可以弹出一个我们指定得窗口,仅此而已那么在Prism当中,Dialog指的什么?
Prism提供了一组对话服务,封装了常用的对话框组件的功能,例如:
Dialog其实也是一组用户控件,我们可以创建一个子模块,然后不需要继承IModule,继承了也没有关系,只要不加载该子模块就行,这样我们可以把他当作对话框或者子模块使用,而不需要改动太多代码。值得一提的是,默认情况下这个控件会嵌入到窗体中弹出,所以我们可以定义弹出窗体的一些属性:
<prism:Dialog.WindowStyle>
<Style TargetType="Window">
<Setter Property="prism:Dialog.WindowStartupLocation" Value="CenterOwner" />
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome CaptionHeight="0" ResizeBorderThickness="5" />
</Setter.Value>
</Setter>
<Setter Property="WindowStyle" Value="None" />
<Setter Property="AllowDrop" Value="True" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="ShowInTaskbar" Value="False" />
<Setter Property="SizeToContent" Value="WidthAndHeight" />
</Style>
</prism:Dialog.WindowStyle>
然后我们Dialog的ViewModel需要继承接口IDialogAware,这个接口我们在后面再细说。
我们在App类的重写函数中注册对话框服务:
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterDialog<DialogA.Views.DialogA>();
containerRegistry.RegisterDialog<DialogA.Views.DialogA>("DialogA");
containerRegistry.RegisterDialog<DialogA.Views.DialogA, DialogA.ViewModels.DialogAViewModel>();
}
如果没有传递字符串参数,则DialogName默认为类名(View的类名)。也可以在注册的使用将View和ViewModel进行绑定,不过一般就是View的xaml代码中使用
prism:ViewModelLocator.AutoWireViewModel="True"
进行关联。
要调用Dialog,我们需要拿到IDialogService接口的实现,而这个实现容器中已经注册过了,我们只需要在构造函数中注入即可。
private IDialogService dialog;
public MainWindowViewModel(IRegionManager regionManager,IDialogService dialogService)
{
this.region = regionManager;
this.dialog = dialogService;
}
然后调用这两个方法中的一个就可以打开对话框:
this.dialog.ShowDialog("DialogA");//模态对话框:父窗体禁止使用
this.dialog.Show("DialogA");//非模态对话框:父窗体可以继续使用
public interface IDialogService
{
void Show(string name, IDialogParameters parameters, Action<IDialogResult> callback);
void Show(string name, IDialogParameters parameters, Action<IDialogResult> callback, string windowName);
void ShowDialog(string name, IDialogParameters parameters, Action<IDialogResult> callback);
void ShowDialog(string name, IDialogParameters parameters, Action<IDialogResult> callback, string windowName);
}
//
// 摘要:
// Extensions for the IDialogService
public static class IDialogServiceExtensions
{
public static void Show(this IDialogService dialogService, string name);
public static void Show(this IDialogService dialogService, string name, Action<IDialogResult> callback);
public static void ShowDialog(this IDialogService dialogService, string name);
public static void ShowDialog(this IDialogService dialogService, string name, Action<IDialogResult> callback);
}
接口的实现中,最多有四个参数:
拓展方法中最多有两个参数,其中省略了parameters和windowName。
private void OpenDialog()
{
IDialogParameters parameters = new DialogParameters();
parameters.Add("param1", "Hello");
this.dialog.ShowDialog("DialogA", parameters, DialogCallback);
}
private void DialogCallback(IDialogResult result)
{
//对话框关闭之后的回调函数,可以在这解析结果。
ButtonResult result1 = result.Result;
var param = result.Parameters.GetValue<string>("param1");
}
这个接口一般由ViewModel来继承。
//
// 摘要:
// Interface that provides dialog functions and events to ViewModels.
public interface IDialogAware
{
//
// 摘要:
// The title of the dialog that will show in the window title bar.
string Title { get; }
//
// 摘要:
// Instructs the Prism.Services.Dialogs.IDialogWindow to close the dialog.
event Action<IDialogResult> RequestClose;
//
// 摘要:
// Determines if the dialog can be closed.
//
// 返回结果:
// If true the dialog can be closed. If false the dialog will not close.
bool CanCloseDialog();
//
// 摘要:
// Called when the dialog is closed.
void OnDialogClosed();
//
// 摘要:
// Called when the dialog is opened.
//
// 参数:
// parameters:
// The parameters passed to the dialog.
void OnDialogOpened(IDialogParameters parameters);
}
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBox
Grid.Row="0"
Height="30"
Margin="20"
HorizontalAlignment="Center"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Text="{Binding Message}" />
<StackPanel Grid.Row="1" Orientation="Horizontal">
<StackPanel.Resources>
<Style TargetType="Button">
<Setter Property="Margin" Value="20" />
<Setter Property="Height" Value="30" />
<Setter Property="Width" Value="80" />
</Style>
</StackPanel.Resources>
<Button Command="{Binding ClickYesCmd}" Content="Yes" />
<Button Command="{Binding ClickNoCmd}" Content="NO" />
</StackPanel>
</Grid>
private void ClickNo()
{
//点击No按钮的时候关闭对话框,并且传递对话框结果(结果中还可以带参数)
RequestClose?.Invoke(new DialogResult(ButtonResult.Cancel));
}
private void ClickYes()
{
//点击Yes按钮的时候关闭对话框,并且传递对话框结果(结果中还可以带参数)
IDialogParameters parameters = new DialogParameters();
parameters.Add("param1", "Hello Baby");
RequestClose?.Invoke(new DialogResult(ButtonResult.OK, parameters));
}
public bool CanCloseDialog()
{
//始终允许关闭对话框
return true;
}
public void OnDialogClosed()
{
//当对话框关闭的时候啥也不干
}
public void OnDialogOpened(IDialogParameters parameters)
{
//打开对话框的时候解析传递进来的参数
Message = parameters.GetValue<string>("param1");
}