【问题标题】:Controlling Windows in WPF when using MVVM pattern使用 MVVM 模式时在 WPF 中控制 Windows
【发布时间】:2011-11-25 12:11:05
【问题描述】:

不久前,我写了这个SO post,寻找一种处理 UI 和业务层交互的好方法,我喜欢使用 MVVM 模式的答案。

所以我做得非常成功,但是我在使用这种模式时遇到了一个问题。实际上,在我的 UI 的某些部分,我的一个按钮应该打开一个对话框,其中包含在 ListView 中显示的项目的详细信息。

我看到这个SO post 询问同样的问题,但我不太明白答案,我想知道它是否适合我的情况。想法是使用Unity 框架,并使用App.Container.Resolve<MyChildView>().ShowDialog() 调用与存储库中的视图关联的窗口。

但是,我的问题是我在项目中实现了与 UI 客户端项目分开的 ViewModel。我这样做是为了在项目的后期需要时能够使用来自另一个客户端的虚拟机。第一个问题,那是模式的错误实现吗?

第二个问题,因为我的 ViewModels 项目实际上不在客户的项目中,因此我无权访问 App 全局变量。因此,我认为我不能使用我在前面提到的帖子中找到的解决方案。有什么解决办法吗?

【问题讨论】:

    标签: c# .net design-patterns mvvm


    【解决方案1】:

    1) 你的实现完全没有错。我经常将 UI、VM 和模型分成单独的程序集。

    2) 正如您所提到的,在 VM 中引用 App 是不合适的。将 App 视为“UI 类”并将其视为此类。您是否考虑过将适当的 UnityContainer 注入您的 VM 中?

    如果注入容器不是您的选择,请考虑在您的解决方案中添加控制器或使用您提到的SO post 中其他答案所建议的调解器模式。

    【讨论】:

    • 正如在另一篇文章中所讨论的,只要您将视图的引用提供给模型视图,使用控制器就会“破坏”MVVM 模式,对吗?至于 Unity 容器,如何在不引用视图的情况下将其注入到 MV 中?
    • @SRKX ,我不同意控制器破坏 MVVM。我通常在我的 UI 程序集中添加一个 Controller 类,它实现了一个接口(在 VM 程序集或公共程序集中定义的 IController)。我的虚拟机注入了一个 IController。您不想在 Controller 上公开任何会创建对 UI 程序集的依赖关系的成员。例如,不要公开 MyChildView 成员,而是公开一个可以完成您想要的工作的方法。
    • 如果您需要在解耦方面走极端,并且不喜欢将控制器与具体 UI 类耦合的想法,请考虑在您的视图上实现接口。执行 _injectedContainter.Resolve<IAnyChildView>().ShowDialog() 的 VM 或 Controller 没有任何问题。
    【解决方案2】:

    试试这个。设置一个新线程,初始化并显示您的窗口(您也可以使用ShowDialog() 代替Show()),然后通过调用Dispatcher.Run() 将线程转换为UI 线程,这将阻塞直到窗口关闭。然后,之后,您可以随心所欲地处理对话结果。

    new Thread(() =>
    {
        MyDialogWindow m = new MyDialogWindow();
        m.ShowDialog();
        Dispatcher.Run();
        // Handle dialog result here.
    }).Start();
    

    请务必在您的对话框中添加一个事件,以便在您关闭窗口时让 Dispatcher 停止。将此添加到对话框的构造函数中:

    Closed += (_,__) => Dispatcher.InvokeShutdown();
    

    【讨论】:

    • 但这意味着从 VM 内部引用一个视图,这与该模式的想法是相反的,不是吗?
    • 不要从视图模型中引用它。创建一个单独的类来执行此操作,它从对话框窗口返回值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-03
    • 2016-07-12
    • 2011-12-05
    • 2012-02-19
    • 2017-05-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多