【问题标题】:How do I subscribe to PropertyChanged event in my ViewModel?如何在我的 ViewModel 中订阅 PropertyChanged 事件?
【发布时间】:2011-12-11 02:49:00
【问题描述】:

我的核心功能封装在ViewModelBase

现在我想看看 ViewModelBase 何时引发 PropertyChanged 事件并对其采取行动。例如,当 ViewModelBase 上的一个属性发生更改时 - 我想更改我的 ViewModel 上的属性

我如何做到这一点?

public class MaintainGroupViewModel : BaseViewModel<MEMGroup>
    {


public abstract class BaseViewModel<T> : NotificationObject, INavigationAware
        where T : Entity
    {

【问题讨论】:

  • 你的NotificationObject实现INotifyPropertyChanged接口了吗?如果是这样,那么它是基本事件订阅。如果没有,那么你应该实现INotifyPropertyChanged。

标签: c# mvvm inotifypropertychanged


【解决方案1】:

订阅属性更改的直接方法是使用INotifyPropertyChanged,如果您的BaseViewModel 实现了它:

PropertyChanged += (obj, args) =>
   { System.Console.WriteLine("Property " + args.PropertyName + " changed"); }

如果不是,那么它必须是DependencyObject,并且您的属性必须是DependencyProperties(这可能是一种更复杂的方式)。

This article 描述如何订阅DependencyProperty 更改。

【讨论】:

    【解决方案2】:

    通常我在类 Constructor 中使用注册到PropertyChanged 事件

    public MyViewModel()
    {
        this.PropertyChanged += MyViewModel_PropertyChanged;
    }
    

    我的 PropertyChanged 事件处理程序如下所示:

    void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        switch (e.PropertyName)
        {
            case "SomeProperty":
                // Do something
                break;
        }
    }
    

    【讨论】:

    • 在处理时有没有办法摆脱“魔术字符串”。 (我没有使用 C# 6)
    • @Marshal 我不确定,this blog post by Josh Smith 呢?
    • 我认为这是一个很好的解决方案,并且足够可测试。感谢您指向文章。
    • @Rachel:您如何看待使用这种技术来避免“Duplicate RaisePropertyChanged for Cascading Read-Only Properties”(“stackoverflow.com/questions/46314677/…)?
    • @Tom 我认为这很好。给你一个问题的答案:)
    【解决方案3】:

    我担心您实际上是在将派生类中的属性“手动绑定”(不好)到基类上的值(也不好)。使用继承的全部意义在于派生类可以访问基类中的内容。使用protected 修饰符来指示事物只能被派生类访问。

    我会建议这个(可能)更正确的方法:

    基类:

    protected virtual void OnMyValueChanged() { }
    

    派生类:

    protected override void OnMyValueChanged() { /* respond here */ }
    

    真的,在您正在编写的类的基类中订阅一个事件似乎是令人难以置信的倒退——如果您要围绕自己进行组合,那么使用继承而不是组合有什么意义?您实际上是在要求一个对象在发生某事时告诉自己。为此,您应该使用方法调用。

    就“当 ViewModelBase 上的一个属性发生更改时 - 我想更改我的 ViewModel 上的属性”,...它们是同一个对象!

    【讨论】:

    • 是的,它确实有味道 :) 我的场景是这样的......我有基本功能,但在这种特定情况下,当一些基本数据发生变化时,我想重新排列我的 ViewModel 上的一些数据。基类维护主要数据实体(假设是客户),我想在客户更改时更新更多 UI。
    • 我仍然建议使用方法而不是事件,并在必要时使用组合而不是继承:创建一个包含基本 ViewModel 的新对象。否则每个人仍然可以访问基本 ViewModel 的“基本”功能,实际上您似乎正在修改它,因此派生类不适合。
    • 也许方法是一种方法。另一个例子。基类维护我的数据输入表单的“状态”。像新建,编辑,添加。一堆 UI 绑定到这个状态。在我的虚拟机中,我也想知道这种状态变化。我可以创建方法 OnStateChange,也可以订阅 PropertyChanged。您认为需要重构还是只创建方法?方法可能看起来更“干净”
    • 该功能属于基本视图模型——尤其是像 OnStateChange 这样通用的东西。你能再举一个例子吗? :)
    • 我明白了。基本上,订阅自己的事件是一种代码味道。覆盖 OnStateChange 并调用 base.OnStateChange 是处理这种情况的正确方法。两种实现相同的功能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-23
    • 1970-01-01
    • 2011-02-05
    • 2020-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多