代码之家  ›  专栏  ›  技术社区  ›  Steve Dunn supercat

在模型视图视图模型中打开新窗口的最佳位置

  •  9
  • Steve Dunn supercat  · 技术社区  · 17 年前

    我有一个MVVM应用程序。在其中一个ViewModels中是“FindFileCommand”,它填充ObservableCollection。然后,我在同一个ViewModel中实现了一个“RemoveFilesCommand”。然后,该命令将弹出一个窗口,以获取更多的用户输入。

    在保持MVVM范式的同时,在哪里/什么是实现这一点的最佳方法?以某种方式 做:

    new WhateverWindow( ).Show( ) 

    在视图中,模型似乎是错误的。

    干杯

    史蒂夫

    7 回复  |  直到 17 年前
        1
  •  2
  •   Nikhil Kothari    16 年前

    我个人将此场景视为主窗口视图模型希望为最终用户完成一项任务的场景。

    它应该负责创建并初始化任务。视图应该负责创建和显示子窗口,并将任务用作新实例化窗口的视图模型。

    窗口使用通知关闭自身。如果存在后续工作,则提交任务后,父视图模型将使用通知执行其他工作。

    我有一个Silverlight的实现。看见 http://www.nikhilk.net/ViewModel-Dialogs-Task-Pattern.aspx

        2
  •  1
  •   Tom Deleu    17 年前

    在Jaime Rodriguez和Karl Shifflet的Southridge realty示例中,他们正在viewmodel中创建窗口,更具体地说是在绑定命令的执行部分:

        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); 
        } 
    

    以下是链接: http://blogs.msdn.com/jaimer/archive/2009/02/10/m-v-vm-training-day-sample-application-and-decks.aspx

    我想这不是什么大问题。毕竟,Viewmodel充当了视图和业务层/数据层之间的“粘合剂”,所以耦合到视图(UI)是正常的。。。

        3
  •  1
  •   wekempf    17 年前

    玛瑙( http://www.codeplex.com/wpfonyx )将为此提供一个相当不错的解决方案。例如,查看ICommonDialogProvider服务,该服务可从ViewModel中使用,如下所示:

    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();
    

    然后,您必须确保该视图具有IRemoveFiles服务的实现,您可以使用多个选项。

    Onyx还没有准备好发布,但是代码完全可以工作,至少可以作为参考点使用。我希望很快发布稳定的V1接口,并将尽快发布我们有体面的文档和样本。

        4
  •  0
  •   timothymcgrath    17 年前

    我也遇到了MVVM的这个问题。我的第一个想法是设法找到一种不使用对话框的方法。使用WPF比使用对话框更容易想出一种更巧妙的方法来做事情。

    如果不可能,最好的选择似乎是让ViewModel调用一个共享类来从用户那里获取信息。ViewModel应该完全不知道正在显示对话框。

    对于返回大量数据的更高级对话框,helper方法应该返回一个包含对话框中所有信息的对象。

        5
  •  0
  •   Cameron MacFarland    17 年前

    我不得不说,服务是我们的出路。

    通过这种方式来测试,您可以在测试中模拟服务接口,而ViewModel也不明智。就ViewModel而言,它向服务请求了一些信息,并收到了所需的信息。

        6
  •  0
  •   Florian    16 年前

    我们正在做的事情是这样的,这里描述的是: http://www.codeproject.com/KB/WPF/DialogBehavior.aspx?msg=3439968#xx3439968xx

        7
  •  -1
  •   RS Conley    17 年前

    用于此类对话框。我将其定义为findFileCommand的嵌套类。如果在许多命令中使用基本对话框,我会在这些命令可访问的模块中定义它,并让命令相应地配置对话框。

    命令对象足以显示对话框如何与软件的其余部分交互。在我自己的软件中,命令对象驻留在它们自己的库中,因此对话框对系统的其余部分是隐藏的。

    在我看来,做任何喜欢的事都是过分的。此外,试图将其保持在最高级别通常需要创建大量额外的接口和注册方法。这是一个为小增益编码很多。

    在少数几个对话框对多个命令有用的实例中,我将其定义在所有命令共用的模块中。然而,在我的软件中,20个对话框中可能有1个是这样的。主要的异常是文件打开/保存对话框。如果一个对话框被几十个命令使用,那么我将完整地定义一个接口,创建一个表单来实现该接口并注册该表单。