【问题标题】:Wrapping properties in WPF-compatible properties to implement INotifyPropertyChanged在 WPF 兼容的属性中包装属性以实现 INotifyPropertyChanged
【发布时间】:2014-08-13 23:01:47
【问题描述】:

在我的 WPF 应用程序中,我的 Model 类继承自 ParentClass 类:

Model : ParentClass, INotifyPropertyChanged

我的应用程序只是为了提供一个 UI 来测试和验证ParentClass。所以Model 真的只不过是覆盖在ParentClass 上的INotifyPropertyChanged 实现

但是我仍然需要从该父类访问数据并让它响应 UI。

假设SlicingParentClass 中的属性,WPFSlicingModel 中的属性,这就是我目前的做法。我将每个父属性包装在与 WPF 兼容的属性中。

public Thickness WPFSlicing
{
    get { return Slicing; }
    set
    {
        Slicing = value;
        OnPropertyChanged("Slicing");
    }
}

有没有更聪明的方法来做到这一点?我的父类中有很多属性,这似乎是一个非常平庸的方法。

【问题讨论】:

  • 是的,您需要为每个 setter 调用 OnPropertyChanged("propertyName") :(
  • 看来你对View、Model和ViewModel没有很好的分离。也许您可以编辑您的问题以显示您的哪些类对应于 MVVM 域。
  • 在模型中实现INotifyPropertyChanged不常见吗?
  • 您将需要它。但也许你正在寻找这个。 msdn.microsoft.com/en-us/library/ms165394.aspx
  • 如果您的 VS 版本支持宏(或 Macro Alternatives),我发现只记录一个宏会为我写出所有属性更改内容是最快的。如果你有兴趣,我有一个例子here

标签: c# wpf mvvm inotifypropertychanged


【解决方案1】:

这是一个非常有趣的问题。

通常,我发现在 MVVM 应用程序中,您会尝试将模型隔离为视图模型的最终结果(产品/数据片段)。例如,如果您有一家自行车商店,您会将 Storefront 视为 View,将 Sales Person 视为 ViewModel(假设这是一个按订单制造的可定制自行车),而 Model 则视为完成的 Bicycle 对象。

在构建自行车的情况下,虽然它处于需要表示的“原型设计”阶段,但我倾向于将其包装在 ViewModel 中——因为其中包含逻辑。这似乎是一个额外的步骤,但最终,您可以在构建 ViewModel 时对其进行验证。如果您的模型无法灵活地将 INotifyPropertyChanged 添加到其中(或者如果它是从服务生成的),那么如果您的自行车上有“0”轮胎,您就会遇到问题——这应该会导致问题!

很多人倾向于变得有点懒惰,并将 MVVM 视为一种将原型模型(其中数据输入来回、更新)抽象为模型的模式——实际上它们应该是 ViewModel。

根据示例,我将有一个 MVVM 目录,如下所示:

Models
  -Bicycle (an object that can be passed across a service, etc -- data)
Views
  -BicycleCreatorView (the view or data template of the model)
  -StoreFrontView (the view of the entire store/app)
ViewModels
  -BicycleCreatorViewModel (the view model which CONSTRUCTS a Bicycle model as the end     result)
  -StoreFrontViewModel (the view model for the entire store)

现在,您还可以非常轻松地让 BicycleCreatorViewModel 拥有一个构造函数,该构造函数接受 Bicycle 模型并进行预填充。这并不少见。有人可能会走进一家商店说:“嘿,你能把这个和另一个相似吗?这就是它的样子。”虽然最终结果是拥有另一个实际呈现 Bicycle 对象的属性(可能只是一个 get {}),但 IF 验证很好,并且我们没有什么不寻常的东西,即 0 个轮胎,没有座位(也许这是一个功能?)等。

所以,简而言之——我总是将你的模型(如果你不能以任何方式扩展它)包装到它的 OWN ViewModel 中,为此目的。那将是真正的 MVVM 模式。您始终可以使用诸如 ReactiveUI 或其他可以包装属性的工具包之类的东西。你可能会花更多的时间来做这件事,但最终产品会比其他产品更灵活,更不容易出错。基本上你已经在这样做了,但你可能会重写它,让它看起来“更干净”并且画线了。

理论上,您还可以检查是否可以通过以下方法处理它:

是否有可能使用的面向方面的工具包?如果序列化是一个问题/有问题,也许让你的类部分包含 INotifyPropertyChanged 扩展,然后 XmlIgnore 某些部分?

问题是我们对模型的来源以及您如何使用它知之甚少。希望对您有所帮助或给您一个有趣的想法。很想看看您是否想出一个比标准更“受启发”的解决方案。

【讨论】:

  • 感谢您的长篇回答!实际上,我什至没有想过 ModelParentClass 的 ViewModel,但现在我想起来了,它确实是这样。
【解决方案2】:

我提供另一种观点。这一切都可以用 PostSharp 等 AOP 框架极其简单地解决。 所有您所做的就是将 [NotifyPropertyChanged] 属性附加到您的类,并且您的模型已将所有内容连接起来。

http://www.postsharp.net/aspects/examples/inotifypropertychanged

请注意,这很昂贵,但它可能是一项不错的投资,imo。

Ps,这是观点问题,但我认为让所有 DOMAIN 模型类都实现 INotifyPropertyChanged 并没有什么问题。它不会影响性能,唯一的缺点是它会使代码有点混乱。这就是我所做的,我的域模型实体从 CommonEntityINotifyPropertyChanged 实现。 INotifyPropertyChanged 不是 WPF 的一部分

它有效,而且绝对比将模型包装在视图模型中更好。

【讨论】:

  • 我其实只是个实习生,ParentClass是一门一碰就会让人很生气的课哈哈。否则我肯定会研究 ParentClass 实施 INotifyPropertyChanged
  • 我喜欢这个 AOP 解决方案,但是如果你的合约被锁定,你不能只用标签装饰合约。我同意 AOP 提供了很多很酷的功能,但是如果你被锁定在你的模型来自你无法控制的东西(比如带有合同的通信层 DLL),那么唯一真正的选择就是构建一些东西。但代替问题,上述答案是一种“有趣”的方式,可以避免编写所有额外的“OnNotifyPropertyChanged”等调用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-08
  • 2010-12-07
相关资源
最近更新 更多