Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在ViewModel中订阅PropertyChanged事件?_C#_Mvvm_Inotifypropertychanged - Fatal编程技术网

C# 如何在ViewModel中订阅PropertyChanged事件?

C# 如何在ViewModel中订阅PropertyChanged事件?,c#,mvvm,inotifypropertychanged,C#,Mvvm,Inotifypropertychanged,我将核心功能封装在ViewModelBase 现在我想看看ViewModelBase何时引发PropertyChanged事件并对其进行操作。例如,当ViewModelBase上的一个属性发生更改时-我想更改ViewModel上的属性 我如何做到这一点 public class MaintainGroupViewModel : BaseViewModel<MEMGroup> { public abstract class BaseViewModel<T> :

我将核心功能封装在
ViewModelBase

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

我如何做到这一点

public class MaintainGroupViewModel : BaseViewModel<MEMGroup>
    {


public abstract class BaseViewModel<T> : NotificationObject, INavigationAware
        where T : Entity
    {
公共类MaintainGroupViewModel:BaseViewModel { 公共抽象类BaseViewModel:NotificationObject,INavigationAware 其中T:实体 {
如果您的
BaseViewModel
实现了以下功能,则可以使用订阅属性更改的直接方式:

PropertyChanged += (obj, args) =>
   { System.Console.WriteLine("Property " + args.PropertyName + " changed"); }
如果没有,那么它必须是一个
DependencyObject
,并且您的属性必须是
dependencProperties
(这可能是一种更复杂的方式)


描述如何订阅
DependencyProperty
更改。

我通常使用register来注册类构造函数中的
PropertyChanged
事件

public MyViewModel()
{
    this.PropertyChanged += MyViewModel_PropertyChanged;
}
我的PropertyChanged事件处理程序如下所示:

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

我担心的是,您正在有效地将派生类中的属性“手动绑定”(bad)到基类上的值(也是bad)。使用继承的全部意义在于派生类可以访问基类中的内容。使用
受保护的
修饰符指示内容应仅可由派生类访问

我建议采用(可能)更正确的方法:

基类:

protected virtual void OnMyValueChanged() { }
派生类:

protected override void OnMyValueChanged() { /* respond here */ }
真的,在你正在编写的类的基类中订阅一个事件似乎有着难以置信的倒退——如果你要围绕自己创作,那么使用继承而不是合成有什么意义呢?你实际上是在要求一个对象告诉自己什么时候发生了什么事情。你应该使用方法调用来实现这一点。


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

您的
NotificationObject
是否实现了
INotifyPropertyChanged
接口?如果是,则是基本事件订阅。如果不是,则应实现
INotifyPropertyChanged
。是的,它确实有气味:)我的场景是这样的……我有基本功能,但在这种特定情况下当一些基本数据发生更改时,我想重新排列ViewModel上的一些数据。基类维护主数据实体(比如Customer)当客户发生变化时,我想更新更多的UI。我仍然建议使用方法而不是事件,并且在必要时使用组合而不是继承:创建一个包含基本ViewModel的新对象。否则,每个人仍然可以访问基本ViewModel的“基本”功能,而实际上您似乎正在修改它,所以派生类不适合。也许方法是一种方法。另一个例子。基类维护“状态”我的数据输入表单。如NEW、EDIT、ADD。大量UI绑定到此状态。在我的VM中,我也想知道此状态更改。我可以在StateChange上创建方法,也可以订阅PropertyChanged。您是否认为需要重新组合或仅创建方法?方法可能更“干净”要了解哪些功能应该属于基本视图模型,尤其是像OnStateChange这样的通用功能。你能再举一个例子吗?:)我明白了。基本上,订阅自己的事件是一种代码味道。重写OnStateChange并调用base.OnStateChange是处理这种情况的正确方法。这两种方法都可以实现相同的功能ty.在处理过程中,是否有任何方法可以去除“魔法字符串”。(我不使用C#6)@Marshal我不确定,那又如何?我认为这是一个很好的解决方案,而且是可以测试的。感谢您指出这篇文章。@Rachel:您认为如何使用这种技术来避免“为级联只读属性而重复RaiseProperty更改”()?@Tom我想没关系。给你留了一个问题的答案:)