【问题标题】:How to catch PropertyChanged events in multiple Views?如何在多个视图中捕获 PropertyChanged 事件?
【发布时间】:2016-06-22 14:52:10
【问题描述】:

我最近开始学习 WPF,这使我了解了 MVVM 并最终了解了 MVVM Light,因此仍然是这三个方面的初学者。我正在构建一个布局类似于链接中图片的应用程序 -> Application layout

为了保持良好的代码分离并避免大文件,我决定最好的方法是创建一个主 View,并在其中创建几个较小的 View 每个“ UI 的区域”。根据我在几个教程中阅读的内容,建议为每个 View 维护 1 个 ViewModel。因此,我有一个 Master View / ViewModel,并且有几个 View / ViewModels 同时运行。

最后我有一个单独的模型来跟踪我计划在 UI 中显示的信息。 Model 与可以修改其中数据的外部 API 交互。因此,除了用户请求修改数据(例如:按下按钮或计时器)外,数据也会随着来自 API 的异步事件而改变。这意味着我需要在 ModelViewModels / Views 之间进行双向通信。

问题:

1.您是否同意“每个 UI 区域 1 个视图”?每个 View 有 1 个 ViewModel?

2. 在 Main View-Code-Behind 中,我实例化所有 ViewModel,并在每个 View 中绑定它们,就像在我看到的 MVVM Light 示例中一样:

<UserControl ... DataContext="{Binding Main, Source={StaticResource Locator}}">
<UserControl ... DataContext="{Binding SideBar, Source={StaticResource Locator}}">
<UserControl ... DataContext="{Binding TopBar, Source={StaticResource Locator}}">

这是将多个 ViewModel 实例化并绑定到各自 View 的正确方法吗?

3. 每个 ViewModel 都在其构造函数中传递了对 Main ViewModel(Main ViewModel 本身除外)的引用,这是唯一一个对 Model 的引用。这就是我将几个 ViewModel 连接到模型的方式。这在概念上是否正确?

4. 最初我试图避免使用 MVVM Light 或其他框架,如果我可以使用 RaisePropertyChanged 方法做我想做的所有事情。我可能做错了什么,但是例如,当模型调用 RaisePropertyChanged 时,我可以在主 ViewModel 中捕获该事件,但是它不会传播到其余的 ViewModel,所以我必须自己调用 RaisePropertyChanged第二次:

public MountainTopViewModel()
{
    _model = new MachineStatusModel();
    _model.PropertyChanged += ModelPropertyChanged;
}


void ModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "TestVarModel")
    {
        // do something else if needed
        RaisePropertyChanged("TestVar");
    }
}

我猜这要么不是正确的方法,要么有更好的方法。那么如何在 Model 中的属性发生变化时通知所有 View 和 ViewModel,而不必在不同的地方重新调用方法呢?

对不起,说来话长,我将不胜感激。

【问题讨论】:

    标签: c# wpf mvvm mvvm-light


    【解决方案1】:

    这对我来说似乎不明智:

    模型与可以修改其中数据的外部 API 交互。因此,除了用户请求修改数据(例如:按下按钮或计时器)外,数据也会随着来自 API 的异步事件而改变。这意味着我需要在模型和视图模型/视图之间进行双向通信。

    我会让异步 API 事件驱动视图模型中的更改,不是模型。然后,为了响应来自视图的异步 API 的变化,视图模型会做它通常的事情:更新模型并引发视图响应的事件。视图模型已经扮演了这个角色,所以使用你所拥有的。您的方案增加了您不需要的复杂性,而且比您可能意识到的要复杂得多。您问题中的第 # 4 项只是增加复杂性的冰山一角;相信我,它只会从那里变得更丑陋。不要对自己那样做。你年轻。你有一切为之而活。

    视图模型处理另一个视图模型的PropertyChanged 事件,或者视图模型公开特定的自定义事件,这些事件在特定属性更改值时触发,这并不罕见。它可能有一个NameChanged 事件或其他什么。但据我了解,我认为您的问题没有任何特别需要。

    1. 是的。

    2. 如果 MVVMLight 以您所拥有的方式做事,那么就这样做。 Plunkett's Razor:尽可能遵循你所使用框架的实践。 一致性在编程中是金有很多原因,如果你遵循“规则”,你通常会找到框架会在那里等着帮助你,而不是每一步都与你抗争。这不是自然法则,但它是一个非常可靠的经验法则。

    3. 这在概念上有点不稳定。理想情况下,我们尝试编写不依赖于“父”视图模型的视图模型。您的Library 视图模型必须知道Book 视图模型是什么,因为它包含它们的集合,但如果Book 视图模型不依赖于Library,它通常会更有用。想象一下编写一个Wheel,它对Car 有各种依赖,然后必须实现Bicycle。您是给Bicycle 一个Alternator,还是创建一个虚拟Car?像这样的时候,你开始幻想搬到佛蒙特州的一个公社,用木头制作有用的物品。

    我可能会为每个视图模型设置一个模型类型,并在其构造函数中为所有视图模型提供对它们自己模型的引用。这些模型可能与视图模型具有相同的父子关系。如果您的模型是实体框架或其他东西而不是"POCO" classes,那么是的,每个人都可以使用一个模型或其他任何东西。但是,还是直接交给他们吧。

    【讨论】:

    • “我会让异步 API 事件驱动视图模型中的更改,而不是模型。”我也喜欢这个主意,所以我会听从你的建议。模型将仅充当保存信息的地方(因为它通常来自我目前所读的内容),并且 ViewModel 将触发从 GUI 事件或 API 事件更改信息的事件。此外,每个 ViewModel 都会有一个对 Model 的引用,这样 ViewModel 就可以获取他们需要的所有信息,而不必相互了解。谢谢你们的笑声!
    猜你喜欢
    • 2014-12-08
    • 2011-08-27
    • 1970-01-01
    • 2018-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多