有没有人有任何使用MVVM(Prism)显示窗口对话框的例子? - 例如,执行命令时的配置设置窗口 .
我见过的所有例子都使用了很好的中介模式,但是他们也都在视图模型中引用了一个不理想的视图(我们使用的是DataTemplates)
谢谢
我会使用服务来显示对话框 . 然后,该服务还可以将视图与视图模型链接 .
public interface IDialogService { void RegisterView<TView, TViewModel>() where TViewModel:IDialogViewModel; bool? ShowDialog(IDialogViewModel viewModel); } public interface IDialogViewModel { bool CanClose(); void Close(); }
RegisterView 只是将视图类型与ViewModel类型链接起来 . 您可以在模块初始化中设置这些链接 . 这比尝试让模块在应用程序的顶层注册datatemplates更简单 .
RegisterView
ShowDialog 显示要显示的ViewModel . 它返回true,false和null表示关闭,就像 Window.ShowDialog 方法一样 . 该实现只是从容器中创建一个类型为 TView 的新视图,将其挂钩到提供的ViewModel,并显示它 .
ShowDialog
Window.ShowDialog
TView
IDialogViewModel 为ViewModel提供了一种机制,可以进行验证并取消关闭对话框 .
IDialogViewModel
我有一个标准的对话窗口,里面有一个内容控件 . 调用 ShowDialog 时,它会创建一个新的标准对话框,将视图添加到内容控件,挂钩ViewModel并显示它 . 标准对话框已经有[OK]和[Cancel]按钮,其中包含从 IDialogViewModel 调用正确方法的相应逻辑 .
我这样做的方法是使用中介模式 . 当ViewModel想要显示一个对话框时,它会发送一条消息,该消息由应用程序的主窗口拾取 . 该消息包含对话框使用的ViewModel的实例 .
然后,主窗口构造对话框窗口的实例,将视图模型传递给它并显示对话框 . 对话框的结果将传递回原始消息中的调用者 .
它看起来像这样:
在您的视图模型中:
DialogViewModel viewModel = new DialogViewModel(...); ShowDialogMessage message = new ShowDialogMessage(viewModel); _messenger.Broadcast(message); if (message.Result == true) { ... }
在主窗口中代码隐藏:
void RecieveShowDialogMessage(ShowDialogMessage message) { DialogWindow w = new DialogWindow(); w.DataContext = message.ViewModel; message.Result = w.ShowDialog(); }
我希望这足以让你有这个想法......
正如我理解你上面的评论,问题不在于显示关于隐藏它们的对话框 . 有两种方法可以解决这个问题:
存在多个允许这样做的框架 - Prism的事件聚合器将是其中之一 . 在这种情况下,View将订阅一个事件(例如,MyDialogResultValidated),并且在接收到该事件时,它将累积设置DialogResult . 如果验证成功,ViewModel(在其SaveCommand中)将触发事件 .
在这种情况下,视图和叠加层的可见性将绑定ViewModel的IsVisible属性,该属性将由SaveCommand实现相应地设置,或者ViewModel需要显示View时 .
第一种方法需要在代码隐藏中使用一些代码,需要添加全局事件,并且(可以说)更少MVVM-ish . 第二种方法需要实现(或使用其他人的实现)覆盖,但不需要在代码隐藏中使用任何代码,不需要具有全局事件,并且(可论证的)更多MVVM-ish .
我同意,根据MVVM模式使用服务显示对话框是最简单的解决方案 . 但是,我也问过自己,如果我的项目中有3个程序集Model,ViewModel,View和MVVM模式程序集ViewModel都有对Model的引用,而View对Model和ViewModel都应该在哪里放置DialogService类?如果我将一个放在ViewModel程序集中 - 我没有机会创建DialogView实例;另一方面,如果我将DialogService放在View程序集中,我应该如何在ViewModel类中注入它?
所以,我会重新审视一下Advanced MVVM scenarios with Prism Part: Using Interaction Request Objects
作为这种方法的例子:
DialogViewModelBase
public abstract class DialogViewModelBase : ViewModelBase { private ICommand _ok; public ICommand Ok { get { return _ok ?? (_ok = new DelegateCommand(OkExecute, CanOkExecute)); } } protected virtual bool CanOkExecute() { return true; } protected virtual void OkExecute() { _isSaved = true; Close = true; } private ICommand _cancel; public ICommand Cancel { get { return _cancel ?? (_cancel = new DelegateCommand(CancelExecute, CanCancelExecute)); } } protected virtual bool CanCancelExecute() { return true; } protected virtual void CancelExecute() { Close = true; } private bool _isSaved = false; public bool IsSaved { get { return _isSaved; } } private bool _close = false; public bool Close { get { return _close; } set { _close = value; RaisePropertyChanged(() => Close); } } }
CreateUserStoryViewModel:
public class CreateUserStoryViewModel : DialogViewModelBase { private string _name = String.Empty; public string Name { get { return _name; } set { _name = value; RaisePropertyChanged(() => Name); } } }
CreateUserStoryRequest
private InteractionRequest<Notification> _createUserStoryRequest; public InteractionRequest<Notification> CreateUserStoryRequest { get { return _createUserStoryRequest ?? (_createUserStoryRequest = new InteractionRequest<Notification>()); } }
CreateUserStory Command
private void CreateUserStoryExecute() { CreateUserStoryRequest.Raise(new Notification() { Content = new CreateUserStoryViewModel(), Title = "Create User Story" }, notification => { CreateUserStoryViewModel createUserStoryViewModel = (CreateUserStoryViewModel)notification.Content; if (createUserStoryViewModel.IsSaved) { _domainContext.CreateUserStory( new UserStory(){ Name = createUserStoryViewModel.Name, }); } }); }
XAML:
<!--where xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ir="clr-namespace:Microsoft.Practices.Prism.Interactivity.InteractionRequest;assembly=Microsoft.Practices.Prism.Interactivity"--> <i:Interaction.Triggers> <ir:InteractionRequestTrigger SourceObject="{Binding CreateUserStoryRequest}"> <ir:PopupChildWindowAction> <ir:PopupChildWindowAction.ChildWindow> <view:CreateUserStory /> </ir:PopupChildWindowAction.ChildWindow> </ir:PopupChildWindowAction> </ir:InteractionRequestTrigger> </i:Interaction.Triggers>
您可能对以下示例应用程序感兴趣:
http://compositeextensions.codeplex.com
它使用Prism2和PresentationModel(又名MVVM)模式 . 示例应用程序包含模式对话框 .
它不是Prism,但这个MVVM demo有一个完全MVVM的选项对话框 .
6 回答
我会使用服务来显示对话框 . 然后,该服务还可以将视图与视图模型链接 .
RegisterView
只是将视图类型与ViewModel类型链接起来 . 您可以在模块初始化中设置这些链接 . 这比尝试让模块在应用程序的顶层注册datatemplates更简单 .ShowDialog
显示要显示的ViewModel . 它返回true,false和null表示关闭,就像Window.ShowDialog
方法一样 . 该实现只是从容器中创建一个类型为TView
的新视图,将其挂钩到提供的ViewModel,并显示它 .IDialogViewModel
为ViewModel提供了一种机制,可以进行验证并取消关闭对话框 .我有一个标准的对话窗口,里面有一个内容控件 . 调用
ShowDialog
时,它会创建一个新的标准对话框,将视图添加到内容控件,挂钩ViewModel并显示它 . 标准对话框已经有[OK]和[Cancel]按钮,其中包含从IDialogViewModel
调用正确方法的相应逻辑 .我这样做的方法是使用中介模式 . 当ViewModel想要显示一个对话框时,它会发送一条消息,该消息由应用程序的主窗口拾取 . 该消息包含对话框使用的ViewModel的实例 .
然后,主窗口构造对话框窗口的实例,将视图模型传递给它并显示对话框 . 对话框的结果将传递回原始消息中的调用者 .
它看起来像这样:
在您的视图模型中:
在主窗口中代码隐藏:
我希望这足以让你有这个想法......
正如我理解你上面的评论,问题不在于显示关于隐藏它们的对话框 . 有两种方法可以解决这个问题:
存在多个允许这样做的框架 - Prism的事件聚合器将是其中之一 . 在这种情况下,View将订阅一个事件(例如,MyDialogResultValidated),并且在接收到该事件时,它将累积设置DialogResult . 如果验证成功,ViewModel(在其SaveCommand中)将触发事件 .
在这种情况下,视图和叠加层的可见性将绑定ViewModel的IsVisible属性,该属性将由SaveCommand实现相应地设置,或者ViewModel需要显示View时 .
第一种方法需要在代码隐藏中使用一些代码,需要添加全局事件,并且(可以说)更少MVVM-ish . 第二种方法需要实现(或使用其他人的实现)覆盖,但不需要在代码隐藏中使用任何代码,不需要具有全局事件,并且(可论证的)更多MVVM-ish .
我同意,根据MVVM模式使用服务显示对话框是最简单的解决方案 . 但是,我也问过自己,如果我的项目中有3个程序集Model,ViewModel,View和MVVM模式程序集ViewModel都有对Model的引用,而View对Model和ViewModel都应该在哪里放置DialogService类?如果我将一个放在ViewModel程序集中 - 我没有机会创建DialogView实例;另一方面,如果我将DialogService放在View程序集中,我应该如何在ViewModel类中注入它?
所以,我会重新审视一下Advanced MVVM scenarios with Prism Part: Using Interaction Request Objects
作为这种方法的例子:
DialogViewModelBase
CreateUserStoryViewModel:
CreateUserStoryRequest
CreateUserStory Command
XAML:
您可能对以下示例应用程序感兴趣:
http://compositeextensions.codeplex.com
它使用Prism2和PresentationModel(又名MVVM)模式 . 示例应用程序包含模式对话框 .
它不是Prism,但这个MVVM demo有一个完全MVVM的选项对话框 .