PropertyChanged的身体在哪里?

时间:2015-08-07 13:54:33

标签: c# eventhandler propertychanged

我想知道PropertyChanged的正文(实例)在哪里?

    private int age;
    public int Age
    {
        get { return age; }
        set 
        { 
            age = value;
            OnPropertyChanged("age");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

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

在上面,"公共事件PropertyChangedEventHandler PropertyChanged"只是一个声明,但在下一行之后突然PropertyChanged事件处理程序看起来实例化,然后才能被调用。会发生什么?

要添加一些信息, 我使用WPF工作。 没有明确的事件订阅者代码。但是在xaml中有一个线索。

<TextBox x:Name="txtAge" Text="{Binding Age}/>

那么,当xaml中存在Binding时,是否会自动添加订阅者代码?

3 个答案:

答案 0 :(得分:2)

这是类字段事件。它有点像自动实现的属性 - C#编译器提供了实现。 (如果语法更像是自动实现的属性,我更喜欢它,但这是另一回事。)

来自C#5规范的第10.8.1节:

  

编译类似字段的事件时,编译器会自动创建存储以保存委托,并为添加或删除委托字段的事件处理程序的事件创建访问器。添加和删​​除操作是线程安全的,并且可以(但不是必须)在实例事件的包含对象上保持锁(第8.12节)或静态类型对象(第7.6.10.6节)时完成事件

     

因此,形式的实例事件声明:

class X
{
     public event D Ev;
}
     

将被编译为等同于:

的东西
class X
{
    private D __Ev;  // field to hold the delegate
    public event D Ev {
        add {
            /* add the delegate in a thread safe way */
        }
        remove {
            /* remove the delegate in a thread safe way */
        }
    }
}
     

在类X中,对+ =和 - =运算符左侧的Ev的引用会导致调用add和remove访问器。对Ev的所有其他引用都被编译为引用隐藏字段__Ev(第7.6.4节)。名称“__Ev”是任意的;隐藏字段可以有任何名称或根本没有名称。

答案 1 :(得分:0)

PropertyChanged是一个事件 - 如果没有人订阅该事件,它将为null,否则它将为非null。您的API用户将按以下方式订阅:

Person p = new Person(...);
p.PropertyChanged += MyHandler;

void MyHandler(object sender, PropertyChangedEventArgs args) { ... }

此外,您的空检查模式不是100%安全。检查后,它可能会从非null变为null。

试试这个:

var callback = PropertyChanged;
if(callback != null) {
    callback(this, new PropertyChangedEventArgs(name));
}

答案 2 :(得分:0)

另一个对象(通常)将订阅提供的事件处理程序PropertyChanged

当条件满足时,类本身将调用它的OnPropertyChanged事件,然后将其PropertyChanged事件字段检查为null。如果此字段不为null,则表示事件的订阅者已初始化它,因此可以调用它。

订阅将如下所示:

InstanceOfYourClass.PropertyChanged += SomeFunctionThatHandlesIt;

private void SomeFunctionThatHandlesIt(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "SomeProperty")
    {
        DoSomething();
    }
}