我想知道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时,是否会自动添加订阅者代码?
答案 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();
}
}