正在处理OnPropertyChanged



我并不精通基于事件的编程。基本上,我仍然在磕磕碰碰。我正在尝试设置一些东西,但即使有教程,我也无法理解。我想做的(用文字)如下:

  1. 我有一个属性更改的数据对象。我在属性的setter中注意到了这一点,并希望引发属性已更改的事件。

  2. 在其他地方(在一个完全不同的类中),我想知道这个对象的属性已经更改,并采取一些操作。

现在我确信这是一个足够常见的场景,但我的谷歌功能让我失望了。我只是不理解http://msdn.microsoft.com/en-us/library/ms743695.aspx.

我有这个:

public class ChattyClass {
  private int someMember;
  public event PropertyChangedEventHandler PropertyChanged;
  public int SomeMember {
    get {
      return this.someMember;
    }
    set {
      if (this.someMember != value){
        someMember = value;
        // Raise event/fire handlers. But how?
      }
   }
}
public class NosyClass{
  private List<ChattyClass> myChatters;
  public void addChatter(ChattyClass chatter){
    myChatters.add(chatter);
    // Start listening to property changed events
  }
  private void listner(){
    // I want this to be called when the PropertyChangedEvent is called
    Console.WriteLine("Hey! Hey! Listen! A property of a chatter in my list has changed!");
  }
}

我该怎么做才能把它连接起来?

关于将我指向链接的评论:

在我看到的例子中:

protected void OnPropertyChanged(string name)
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(name));
    }
}

我不明白的是:

  • 为什么这不只是呼叫PropertyChanged(this, new PropertyCHangedEventArgs(name))
  • PropertyChanged在哪里分配
  • 作业是什么样子的

您必须触发事件。在MSDN上的例子中,他们制作了一个受保护的方法OnPropertyChanged来更容易地处理这个问题(并避免重复代码)。

// Create the OnPropertyChanged method to raise the event 
protected void OnPropertyChanged(string name)
{
    PropertyChangedEventHandler handler = PropertyChanged;
    if (handler != null)
    {
        handler(this, new PropertyChangedEventArgs(name));
    }
}

这个方法的作用是查看是否分配了一个事件处理程序(如果没有分配,只调用它,就会得到一个NullReferenceException)。如果分配了一个,请调用此事件处理程序。提供的事件处理程序必须具有PropertyChangedEventHandler委托的签名。此签名为:

void MyMethod(object sender, PropertyChangedEventArgs e)

其中,第一个参数必须是对象类型,并表示引发事件的对象,第二个参数包含此事件的参数。在这种情况下,您自己的类会触发事件,从而将this作为参数sender。第二个参数包含已更改的属性的名称。

现在,为了能够对事件的触发做出反应,您必须为类分配一个事件处理程序。在这种情况下,您必须在addChatter方法中指定该值。除此之外,您还必须首先定义处理程序。在NosyClass中,您必须添加一个方法来完成此操作,例如:

private void chatter_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    Console.WriteLine("A property has changed: " + e.PropertyName);
}

正如您所看到的,这个方法对应于我之前解释的签名。在第二个参数中,您将能够找到哪个参数已更改的信息。最后要做的是添加事件处理程序。现在,在addChatter方法中,您必须分配以下内容:

public void AddChatter(ChattyClass chatter)
{
    myChatters.Add(chatter);
    // Assign the event handler
    chatter.PropertyChanged += new PropertyChangedEventHandler(chatter_PropertyChanged);
}

我建议您阅读一些关于.NET/C#中事件的内容:http://msdn.microsoft.com/en-us/library/awbftdfh。我想在阅读/学习了这些之后,事情会对你更清楚。

如果你想快速测试控制台应用程序,你可以在pastebin上找到它(只需复制/粘贴到一个新的控制台应用程序中)。

使用较新版本的C#,可以内联对事件处理程序的调用:

// inside your setter
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MyProperty)));

您也可以使用类似Fody PropertyChanged的东西来自动生成必要的代码(访问他们的GitHub页面链接,并附上示例)。

您查找的链接是MVVM模式和WPF。它不是一个通用的C#实现。你需要这样的东西:

public event EventHandler PropertyChanged;
    public int SomeMember {
        get {
            return this.someMember;
        }
        set {
            if (this.someMember != value) {
                someMember = value;
                if (PropertyChanged != null) { // If someone subscribed to the event
                    PropertyChanged(this, EventArgs.Empty); // Raise the event
                }
            }
        }

public void addChatter(ChattyClass chatter) {
    myChatters.add(chatter);
    chatter.PropertyChanged += listner; // Subscribe to the event
}
// This will be called on property changed
private void listner(object sender, EventArgs e){
    Console.WriteLine("Hey! Hey! Listen! A property of a chatter in my list has changed!");
}

如果你想知道什么属性发生了变化,你需要将事件定义更改为:

public event PropertyChangedEventHandler PropertyChanged;

并将呼叫更改为:

public int SomeMember {
    get {
        return this.someMember;
    }
    set {
        if (this.someMember != value){
            someMember = value;
            if (PropertyChanged != null) { // If someone subscribed to the event
                PropertyChanged(this, new PropertyChangedEventArgs("SomeMember")); // Raise the event
            }
        }
   }
   private void listner(object sender, PropertyChangedEventArgs e) {
       string propertyName = e.PropertyName;
       Console.WriteLine(String.Format("Hey! Hey! Listen! a {0} of a chatter in my list has changed!", propertyName));
   }

为什么这不只是调用PropertyChanged(this,newPropertyCHangedEventArgs(名称))

因为如果没有人将处理程序附加到事件,那么PropertyChanged对象将返回null。所以在调用它之前,你必须确保它不是空的

PropertyChanged在哪里分配?

在"listener"类中。

例如,您可以在其他类中编写:

ChattyClass tmp = new ChattyClass();
tmp.PropertyChanged += (sender, e) =>
    {
        Console.WriteLine(string.Format("Property {0} has been updated", e.PropertyName));
    };

作业是什么样子的?

在C#中,我们对事件使用赋值运算符+=-=。我建议阅读下面的文章,了解如何使用匿名方法表单(上面的示例)和"旧"表单编写事件处理程序。

从原始代码,并结合@Styxxy的答案,我得出:

public class ChattyClass  : INotifyPropertyChanged 
{
  private int someMember, otherMember;
  public int SomeMember
  {
      get
      {
          return this.someMember;
      }
      set
      {
          if (this.someMember != value)
          {
              someMember = value;
              OnPropertyChanged("Some Member");
          }
      }
  }
  public int OtherMember
  {
      get
      {
          return this.otherMember;
      }
      set
      {
          if (this.otherMember != value)
          {
              otherMember = value;
              OnPropertyChanged("Other Member");
          }
      }
  }
  protected virtual void OnPropertyChanged(string propertyName)
  {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
  }
  public event PropertyChangedEventHandler PropertyChanged;
}
public class NosyClass
{
    private List<ChattyClass> myChatters = new List<ChattyClass>();
    public void AddChatter(ChattyClass chatter)
    {
        myChatters.Add(chatter);
        chatter.PropertyChanged+=chatter_PropertyChanged;
    }
    private void chatter_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        Console.WriteLine("A property has changed: " + e.PropertyName);
    }
}

相关内容

  • 没有找到相关文章

最新更新