WPF MVVM:如何更新用户控件数据

WPF MVVM: How to update Usercontrol data

从 WPF 开始,我喜欢 MVVM 模式,其中我有一个 ViewModel 定位器,因为我已经非常习惯 IoC 的使用。但是大多数 blogs/articles 说用户控件不应该有 ViewModel。这是有道理的,但后来我不太明白如何更新它的数据。

例如,假设我有一个用户控件 (UC),它显示一个包含来自硬件设备的数据的图表。我已经实现并准备好 "IProvideGraphData" 接口。但是如何将其注入我的用户控件?

我更希望它在 Usercontrol 构造函数中,但由于 View 不使用 IoC 调用 Usercontrol(通过 ViewModel 定位器),我无法理解如何以干净精确的方式完成此操作。 ..

想法?

不确定您正在阅读哪些博客和文章,但用户控件绝对可以并且确实拥有自己的 ViewModels (VM)。他们总是吗?不!他们有吗?绝对地!这完全取决于用户控件的目的。

如果您将主视图分解为主视图和子视图(即 Window 包含用户控件)以具有明确定义的层次结构,则 ViewModel 也应遵循相同的层次结构。意思是,您的主 Window 具有用于其 DataContext 的主 VM,其中主 VM 将子 VM 公开为属性,而子视图(即 UC)将这些子 VM 属性用于其 DataContext。

这里继承的ViewModelBase实现了INotifyPropertyChanged接口。 Master VM 看起来像这样:

public class MasterViewModel : ViewModelBase
{
    public MasterViewModel()
    {
        ChildVM = new ChildVMType();
    }

    private ChildVMType childVM;
    public ChildVMType ChildVM
    {
        get { return childVM; }
        set { SetProperty(ref childVM, value); }
    }
    ...
}

Master View/ViewModel 将使用 View-First Construction 原则,您可以在 XAML(或您喜欢的任何其他方式)中以声明方式实例化主 VM。关键是,View 实例化了 ViewModel。

<Window.DataContext>
    <local:MainViewModel/>
</Window.DataContext>

另一方面,子 VM 由主 ViewModel(请参阅上面的 VM)实例化,通常在构造函数中遵循 ViewModel-First Construction Principal。

要将子 VM 注入用户控件,您可以在主视图(即 Main Window)的某处执行类似的操作:

<ContentControl>
    <local:MyChildUCview DataContext="{Binding ChildVM}"/>
</ContentControl> 

其中 ChildVM 是 属性 暴露在 Master ViewModel 上(见上文)。

还有很多其他方法可以连接起来,但原理是一样的。

您的目标应该是让子 VM 处理主 VM 不关心的所有逻辑。这将允许更大程度的关注点分离,并将大大提高可维护性和可扩展性。

要允许主 VM 和子 VM 之间进行双向通信,您可以使用事件。例如,您的子 VM 有一个您的主 VM 订阅的事件。当 Child VM 中发生 Master 需要知道的事情时,Child 会引发事件并将所需的参数传递给 Master。 Master 当然可以直接和 Child 对话,因为它是自己的 属性.

如果您真的想学好这一点,我强烈建议您观看 Pluralsight 上的课程,即 "WPF MVVM in Depth" Brian Noyes 的课程。您可以注册免费试用,这应该足以完成本课程。