在保持MVVM范例的同时,最好的方法是在哪里/什么地方进行此操作?在ViewModel中执行以下操作似乎是错误的:
new WhateverWindow( ).Show( )谢谢, Steve
new WhateverWindow( ).Show( )谢谢, Steve
我个人认为这种情况是主窗口视图模型想要向最终用户提供需要完成的任务。
它应该负责创建和初始化任务。视图应该负责创建和显示子窗口,并使用任务作为新实例化窗口的视图模型。
任务可以被取消或提交。当任务完成时,它会发出通知。
窗口使用通知来关闭自身。如果有后续工作,父视图模型使用通知来进行额外的工作。
我认为这是最接近自然/直观的代码后台方法的做法,但重构成将UI无关的关注点拆分为视图模型,而不引入其他概念开销,如服务等。
我在Silverlight中实现了这个功能。请访问http://www.nikhilk.net/ViewModel-Dialogs-Task-Pattern.aspx获取更多详细信息…… 我很乐意听取评论/进一步建议。
ICommonFileDialogProvider provider = this.View.GetService<ICommonDialogProvider>();
IOpenFileDialog openDialog = provider.CreateOpenFileDialog();
// configure the IOpenFileDialog here... removed for brevity
openDialog.ShowDialog();
这与使用具体的OpenFileDialog非常相似,但是它是完全可测试的。您真正需要的解耦程度将成为您的实现细节。例如,在您的情况下,您可能希望一个服务完全隐藏您正在使用对话框的事实。大致如下:
public interface IRemoveFiles
{
string[] GetFilesToRemove();
}
IRemoveFiles removeFiles = this.View.GetService<IRemoveFiles>();
string[] files = removeFiles.GetFilesToRemove();
接下来,您需要确保视图(View)有一个 IRemoveFiles 服务的实现,对于这一点,有几个选项可供选择。
Onyx 还没有准备好发布,但是当前代码完全可以工作并且至少可以用作参考点。我希望尽快稳定 V1 接口,并在我们拥有良好文档和样例时发布。
protected void OnShowDetails ( object param )
{
// DetailsWindow window = new DetailsWindow();
ListingDetailsWindow window = new ListingDetailsWindow();
window.DataContext = new ListingDetailsViewModel ( param as Listing, this.CurrentProfile ) ;
ViewManager.Current.ShowWindow(window, true);
}
我想这不是一个大问题。毕竟,Viewmodel充当视图和业务层/数据层之间的“粘合剂”,所以在我看来与View(UI)耦合是正常的...
我也在MVVM中遇到了这个问题。我的第一个想法是尝试找到不使用对话框的方法。使用WPF可以更容易地想出比对话框更好的方法。
当无法避免时,最好的选择似乎是让ViewModel调用一个共享类来获取用户信息。ViewModel应该完全不知道正在显示对话框。
因此,作为一个简单的例子,如果需要用户确认删除,则ViewModel可以调用DialogHelper.ConfirmDeletion(),它将返回用户是否选择是或否的布尔值。实际的对话框显示将在Helper类中完成。
对于更高级的对话框,返回大量数据,助手方法应返回包含对话框中所有信息的对象。
我同意它不是MVVM的最顺畅的适合方案,但我还没有找到更好的例子。
我必须说,服务是这里的最佳选择。
服务界面提供了一种返回数据的方法。然后,该服务的实际实现可以显示对话框或其他内容以获取接口所需的信息。
这种方式可以在测试中模拟服务接口,而ViewModel则毫不知情。就ViewModel而言,它请求某些信息的服务,并获得了所需的信息。
在极少数情况下,如果对多个命令有用的对话框,我会将其定义在所有命令共用的模块中。然而,在我的软件中,也许只有20个对话框中的1个是这样的。主要例外是文件打开/保存对话框。如果一个对话框被几十个命令使用,那么我会完全定义一个接口,创建一个实现该接口的表单并注册该表单。
如果您的应用程序需要进行国际化本地化,则需要确保考虑到此方案,因为所有表单都不在一个模块中。