PropertyChanged的主体在哪里?
本文关键字:在哪里 主体 PropertyChanged | 更新日期: 2023-09-27 18:06:47
我想知道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时,是否会自动添加订阅者代码呢?
这是一个类似于字段的事件。这有点像自动实现的属性——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"是任意的;隐藏字段可以有任何名称,也可以没有名称。
PropertyChanged是一个事件-如果没有人订阅该事件,它将为空,否则它将为非空。您的API用户将像这样订阅:
Person p = new Person(...);
p.PropertyChanged += MyHandler;
void MyHandler(object sender, PropertyChangedEventArgs args) { ... }
同样,你的空检查模式不是100%安全的。在您检查后,它可能从非空变为空。
试试这个:
var callback = PropertyChanged;
if(callback != null) {
callback(this, new PropertyChangedEventArgs(name));
}
另一个对象(通常)将订阅所提供的事件处理程序PropertyChanged
。
当条件满足时,类本身将调用它的OnPropertyChanged
事件,然后检查它的PropertyChanged
事件字段是否为空。如果此字段不为空,这意味着该事件的订阅者已经初始化了它,因此可以调用它。
订阅看起来像这样:
InstanceOfYourClass.PropertyChanged += SomeFunctionThatHandlesIt;
private void SomeFunctionThatHandlesIt(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "SomeProperty")
{
DoSomething();
}
}