如何在我的ViewModel中订阅PropertyChanged事件?

28

我将核心功能封装在ViewModelBase中。

现在,我想知道何时由ViewModelBase引发了PropertyChanged事件,并对其进行操作。例如,当在ViewModelBase上更改一个属性时 - 我想在我的ViewModel上更改属性。

我该如何实现这个目标呢?

public class MaintainGroupViewModel : BaseViewModel<MEMGroup>
    {


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

1
你的 NotificationObject 是否实现了 INotifyPropertyChanged 接口?如果是,那么这就是基本的事件订阅。如果没有,则应该实现 INotifyPropertyChanged - Anas Karkoukli
3个回答

83

通常我在类构造函数中使用register订阅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
@Marshal 我不确定,那么你觉得Josh Smith的这篇博客文章怎么样? - Rachel
我认为这是一个不错的解决方案,而且足够可测试。感谢指出这篇文章。 - Marshal
@Rachel:你认为使用这种技术也可以避免“级联只读属性的重复RaisePropertyChanged”(“https://stackoverflow.com/questions/46314677/avoiding-duplicate-raisepropertychanged-for-cascading-read-only-properties”)吗? - Tom
1
@Tom 我认为没问题。我也回答了你的问题 :) - Rachel

15
我担心你在派生类中对基类的属性进行了“手动绑定”(不好),将其与基类上的一个值相绑定(同样不好)。继承的整个意义在于派生类可以访问基类中的内容。请使用protected修饰符来表示这些内容应仅对派生类可用。
我建议使用以下(可能更正确的)方法:
基类:
protected virtual void OnMyValueChanged() { }

派生类:

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

在你编写的类的基类中订阅事件似乎非常不合理 - 如果你要在自己周围组合自己,那么使用继承而不是组合有什么意义呢?你实际上是要求一个对象在发生某些事情时告诉自己。这种情况下应该使用方法调用。

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


是的,它确实有点臭 :) 我的情况是这样的... 我有基本功能,但在这种特定情况下,当一些基本数据更改时,我想重新排列我的ViewModel中的某些数据。基类维护主数据实体(比如说顾客),当顾客更改时,我想要更新更多的UI。 - katit
我仍然建议使用方法而不是事件,并在必要时使用组合而非继承:创建一个包含基本ViewModel的新对象。否则,每个人仍然可以访问基本ViewModel的“基本”功能,实际上您似乎正在修改它,因此派生类不适合。 - Kieren Johnstone
那个功能应该属于基本视图模型 - 特别是像OnStateChange这样通用的功能。你能给出另一个例子吗? :) - Kieren Johnstone
1
我明白了。基本上,订阅自己的事件是一种代码异味。重写OnStateChange并调用base.OnStateChange是处理这种情况的正确方法。两种方式都可以实现相同的功能。 - katit
@katit:这就是框架的工作原理。查看各种框架类中的许多事件,你会发现它们具有“On [EventName]”虚拟方法,你可以重写这些方法与触发事件进行交互。当然还有更多内容… - user1228
显示剩余3条评论

2

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

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

如果不是这样,那么它必须是一个“DependencyObject”,你的属性必须是“DependencyProperties”(这可能是一种更复杂的方式)。 本文描述了如何订阅“DependencyProperty”更改。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接