【问题标题】:Best practice for calling View from ViewModel in WPF在 WPF 中从 ViewModel 调用 View 的最佳实践
【发布时间】:2015-03-07 14:42:17
【问题描述】:

我正在寻找一个 wpf 项目的小例子,其中包含在视图之间导航的最佳实践。也许使用框架 MVVM Light 和 NavigationService 或 ServiceLocator。而不是从 ViewModel 调用 View,你是怎么做的呢?你的方法如何?有项目示例吗?

【问题讨论】:

    标签: wpf mvvm


    【解决方案1】:

    我更喜欢 ViewModel 第一种方法。这意味着导航服务将视图模型作为参数,然后根据命名约定创建视图实例并将其加载到框架中。

    navigationService.Navigate<SomePageViewModel>()
    

    这与基于 URI 的导航相比有几个优点,后者是视图优先的方法:

    • 更好的可测试性
    • 依赖注入的可能性
    • 最重要的是:更好的可维护性。如果您重命名或移动页面,则在修复它之前不会编译,这与 URI 不同。 Uri 会在运行时抛出错误

    很遗憾,我现在不能给你我的示例项目,但是实现你自己的很容易

    【讨论】:

    • 如果你有一个带有标签的应用程序怎么办。每次点击 MenuItem 都会打开一个带有 ViewModel 的窗口。你是怎么做到的?
    • 在这种情况下,导航服务不适合,因为它不是基于导航的应用程序:) 您需要具有 Tabs 和 SelectedTab 属性的 MainWindowViewModel。它们可以是 TabViewModelBase 类型。每个选项卡将由具体的 VM 类表示。要打开新选项卡,只需将 TabVM 实例添加到 MainWindowVM 中的选项卡。在 MainWindow 你有 TabControl 与 ItemsSource 绑定到选项卡和 DataTemplateSelector
    • 好吧,也许我误解了你的评论。我所描述的是基于选项卡的 UI,例如 Visual Studio。如果你想打开新窗口(对话框),你应该使用另一个服务类,例如DialogService,因为它的行为与在页面之间导航完全不同
    【解决方案2】:

    我喜欢的一种方式是拥有一个带有内容控件的主窗口。其背后是一个基于共享枚举的具有应用程序状态属性的视图模型。

    枚举旨在表示当前状态,但如果这样更容易,请考虑每个都是您想要显示的视图。

    使用绑定到此属性的模板选择器,我可以控制主窗口内容控件中显示的视图。

    此方法要求您管理一个模板选择器,其中包含您希望成为主要内容的每个枚举值或视图的模板属性。但是模板只需要包含您的视图的一个实例,因此最少需要 XAML。

    在后台,我使用 MVVM light 提供 Viewmodel 定位器数据源,使我的视图非常容易实例化。他们还使用单例视图模型,因此在使用之间管理状态。然后我还使用消息传递框架向我的主窗口视图模型发送消息,告诉它我现在想要哪个状态。这意味着任何视图模型都可以发布消息以切换到另一个状态,而无需知道将是什么视图,但最终主窗口视图模型会管理该转换。

    抱歉这里缺少代码示例,这是我已经做过很多次但我没有干净的示例可以分享的概要。

    希望这足以解释我的方法,但如果这没有意义或不适合您尝试做的事情,请随时发表评论。

    对于对话框... 通常我会重复使用默认对话框,但可以使用相同的原理。而不是作为主窗口控件和虚拟机,有一个用于对话框的辅助控件,它的工作方式相同,但根据请求使其自身可见,并在完成后自行关闭。再次 mvvm light messenger 是你的朋友。

    您的消息包括控制所呈现视图的对话框“状态”。

    这只有在您的设计一次只允许一个对话框时才有效。

    最后,对于标签...

    我会考虑在主视图模型中拥有一个可观察的状态枚举集合。然后通过绑定来构建选项卡。不是我做过的事情,但这就是我要开始的地方。 -

    【讨论】:

    • 谢谢kidshaw!您的方法听起来非常好,但我想知道,如果您想将视图显示为对话框怎么办。你在哪里以及如何解决这个话题?当你说,当前状态......这是一个带有要显示的视图名称的枚举......?再次感谢您的评论
    • 很简单。如果要导航到另一个页面,请使用 NavigationService。如果要显示 Dialog,请创建并使用 DialogService。
    • 重复帖子********
    • 我的回复似乎掉线了。 @Liero - 这是你的替代策略,并不是说你的不正确 - 这只是一个替代方案。
    • 找到了,它作为第二个答案发布!
    猜你喜欢
    • 1970-01-01
    • 2011-08-06
    • 2022-07-05
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多