C# 如何实现包装模型属性的视图模型

C# 如何实现包装模型属性的视图模型,c#,wpf,mvvm,C#,Wpf,Mvvm,假设一个模型带有一个名为Value的属性。该模型实现INotifyPropertyChanged。接下来,假设一个视图模型知道该模型,并为自己提供一个虚拟视图的属性值。此视图模型的实现如下所示: 查看模型代码段 也就是说,此时视图的全部目的是直接将模型的属性传递给视图 视图模型已注册到模型的PropertyChanged事件。每次模型的值更改时,视图模型都会注意到更改并触发PropertyChanged事件本身,以便绑定到视图模型的属性值的视图知道如何更新自身 如果通过视图模型更改模型,则会导致

假设一个模型带有一个名为Value的属性。该模型实现INotifyPropertyChanged。接下来,假设一个视图模型知道该模型,并为自己提供一个虚拟视图的属性值。此视图模型的实现如下所示:

查看模型代码段

也就是说,此时视图的全部目的是直接将模型的属性传递给视图

视图模型已注册到模型的PropertyChanged事件。每次模型的值更改时,视图模型都会注意到更改并触发PropertyChanged事件本身,以便绑定到视图模型的属性值的视图知道如何更新自身

如果通过视图模型更改模型,则会导致多个PropertyChanged调用:

在执行模型后侦听模型更改的视图模型的代码中执行一次。值=值; 由于OnPropertyChanged,再次在值的设置器内部; 我想到的唯一解决方案是将视图模型与模型完全分离。这包括保存模型数据的完整克隆。这样我就可以避免第一次调用PropertyChanged。因为我能够将视图模型的值与模型的值进行比较,所以我可以区分不同的更改来源,即视图模型更改模型或模型被其他来源更改


请注意,视图模型要复杂得多。将模型与视图模型合并不是一个解决方案。

如果视图模型已注册到模型的已更改属性中,并进而引发其自身的属性更改,则视图模型的属性中不需要OnPropertyChanged

删除已更改的OnProperty

ViewModel代码如下所示

public int Value {
    get {
        return Model.Value;
    }
    set {
        if(value != Model.Value) {
            Model.Value = value;
        }
    }
}

viewmodel应该负责更新视图和模型

您基本上已经确定了模型不应该实现INotifyPropertyChanged的原因,并且不应该执行任何要求它实现的操作。没有一种干净、正常的MVVM方法来完成您想要做的事情。这表明你做的MVVM是错误的。当然,MVVM并不是神圣的命令,但它确实工作得很好,而你所做的已经让你陷入了麻烦。你已经制造了一个你不需要制造的问题,并且没有好的解决方案。答案不是选择最差的解决方案;这是为了回到过去,消除设计中的问题

这种设计从根本上说是构思不周的,任何通过增加复杂性来挽救它的企图都将是一团混乱。这是值得做的,因为你从中学到了东西,但不值得再投入更多的时间

您的字面问题“如何实现包装模型属性的viewmodel[property]”的答案是:


就像您在public int-Value示例中所做的那样,但是没有实现INotifyPropertyChanged的模型。

我认为您没有完成标题…抱歉,我已经修复了它。我认为viewmodel应该负责更新模型,而模型不应该实现INotifyPropertyChanged。除了viewmodel之外,还有谁在更改模型?其他型号?其他视图模型?我已经考虑过了,但这似乎不对,因为这是一种间接机制。我不同意。目标是通知视图。您可以通过订阅模型的属性更改事件来实现这一点。保存时必须在视图模型中手动执行。没必要把事情复杂化我想你是对的。我发现这篇文章有点倾向于同一个方向。这在我看来是非常落后的。不需要把事情复杂化?viewmodel将该模型用作引发PropertyChanged的机制。如果您有两个INotifyPropertyChanged的实现,并且您只想要一个,其中一个是viewmodel,那么请去掉一个不是。我必须同意@EdPlunkett。该模型只是一个数据存储库,我认为它是一个数据库,但因为我经常使用它们,所以不知道如何改变它本身。因此,视图模型用于导航来自视图的对模型的更改,以及基于来自视图的交互再次解析模型以在视图中显示。如果有多个视图模型在同一个模型上运行,但未实现INotifyPropertyChanged,您如何知道更改?你建议视图模型必须互相通知吗?@lcm这听起来不是个好主意。在我工作的应用程序中,我们有一个无法避免的地方,用户知道他们必须刷新。这不是问题。
public int Value {
    get {
        return Model.Value;
    }
    set {
        if(value != Model.Value) {
            Model.Value = value;
        }
    }
}