C# 处理 OnPropertyChanged
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12034840/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Handling OnPropertyChanged
提问by Martijn
I'm not well versed in event-based programming. Basically, I'm still stumbling around with it. I'm trying to get something set up, but even with the tutorials, I can't wrap my head around it. What I would like to do (in words) is the following:
我不太精通基于事件的编程。基本上,我仍然在与它磕磕绊绊。我正在尝试设置一些东西,但即使有教程,我也无法理解它。我想做的(用文字)如下:
I have a dataobject where a property changes. I notice this in the setter of the property, and want to raise an event that the property has changed.
Elsewhere (in a different class entirely), I want to know that the property on this object has changed, and take some action.
我有一个属性发生变化的数据对象。我在属性的 setter 中注意到了这一点,并想引发一个属性已更改的事件。
在其他地方(完全在不同的类中),我想知道此对象上的属性已更改,并采取一些措施。
Now I'm sure this is a common enough scenario, but my google-fu is letting me down. I'm simply not understanding http://msdn.microsoft.com/en-us/library/ms743695.aspx.
现在我确定这是一个足够常见的场景,但是我的 google-fu 让我失望了。我只是不理解http://msdn.microsoft.com/en-us/library/ms743695.aspx。
I have this:
我有这个:
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!");
}
}
What do I do to wire this up?
我该怎么办?
Concerning the comment pointing me back to the link:
关于将我指向链接的评论:
In the example I see:
在示例中,我看到:
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
What I'm not understanding:
我不明白的是:
- Why isn't this just calling
PropertyChanged(this, new PropertyCHangedEventArgs(name)) - Where does PropertyChanged get assigned?
- What does the assignment look like?
- 为什么这不只是打电话
PropertyChanged(this, new PropertyCHangedEventArgs(name)) - PropertyChanged 在哪里分配?
- 任务是什么样的?
采纳答案by Styxxy
You have to fire the event. In the example on MSDN, they made a protected method OnPropertyChangedto handle this easier (and to avoid duplicate code).
你必须触发事件。在 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));
}
}
What this method does, is look whether there is an event handler assigned or not (if it is not assigned and you just call it, you'll get a NullReferenceException). If there is one assigned, call this event handler. The event handler provided, has to have the signature of the PropertyChangedEventHandlerdelegate. This signature is:
这个方法的作用是看是否有分配的事件处理程序(如果没有分配并且你只是调用它,你会得到一个NullReferenceException)。如果分配了一个,则调用此事件处理程序。提供的事件处理程序必须具有PropertyChangedEventHandler委托的签名。这个签名是:
void MyMethod(object sender, PropertyChangedEventArgs e)
Where the first parameter has to be of the type object and represents the object that fires the event, and the second parameter contains the arguments of this event. In this case, your own class fires the event and thus give thisas parameter sender. The second parameter contains the name of the property that has changed.
其中第一个参数必须是 object 类型并表示触发事件的对象,第二个参数包含此事件的参数。在这种情况下,您自己的类会触发事件并因此this作为参数提供sender。第二个参数包含已更改的属性的名称。
Now to be able to react upon the firing of the event, you have to assign an event handler to the class. In this case, you'll have to assign this in your addChattermethod. Apart from that, you'll have to first define your handler. In your NosyClassyou'll have to add a method to do this, for example:
现在为了能够对事件的触发做出反应,您必须为该类分配一个事件处理程序。在这种情况下,您必须在您的addChatter方法中分配它。除此之外,您必须首先定义您的处理程序。在你的NosyClass你必须添加一个方法来做到这一点,例如:
private void chatter_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Console.WriteLine("A property has changed: " + e.PropertyName);
}
As you can see, this method corresponds to the signature I explained before. In the second parameter, you'll be able to find the information of which parameter has been changed. Last thing to do, is add the event handler. Now in your addChattermethod, you'll have to assign this:
如您所见,此方法对应于我之前解释的签名。在第二个参数中,您将能够找到更改了哪个参数的信息。最后要做的是添加事件处理程序。现在在你的addChatter方法中,你必须分配这个:
public void AddChatter(ChattyClass chatter)
{
myChatters.Add(chatter);
// Assign the event handler
chatter.PropertyChanged += new PropertyChangedEventHandler(chatter_PropertyChanged);
}
I would suggest you to read something about events in .NET / C#: http://msdn.microsoft.com/en-us/library/awbftdfh. I think after reading/learning this, things will be more clear to you.
我建议您阅读有关 .NET/C# 中事件的一些内容:http: //msdn.microsoft.com/en-us/library/awbftdfh。我想在阅读/学习这个之后,事情对你来说会更清楚。
You can find a console application here on pastebinif you would like to test it quickly (just copy/paste into a new console application).
如果您想快速测试它(只需复制/粘贴到新的控制台应用程序中),您可以在 pastebin 上找到控制台应用程序。
With newer versions of C#, you can inline the call to the event handler:
使用较新版本的 C#,您可以内联对事件处理程序的调用:
// inside your setter
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MyProperty)));
You could also use something like Fody PropertyChangedto automatically generated the necessary code (visit the link to their GitHub page, with samples).
您还可以使用Fody PropertyChanged 之类的东西来自动生成必要的代码(访问其 GitHub 页面的链接,带有示例)。
回答by Vale
The link that you looked is for the MVVMpattern and WPF. It is not a general C# implementation. You need something like this:
您查看的链接是针对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!");
}
If you want to know what property has changed you need to change your event definition to:
如果您想知道哪些属性发生了变化,您需要将事件定义更改为:
public event PropertyChangedEventHandler PropertyChanged;
And change the calling to:
并将调用更改为:
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));
}
回答by ken2k
why isn't this just calling PropertyChanged(this, new PropertyCHangedEventArgs(name))
为什么这不只是调用 PropertyChanged(this, new PropertyCHangedEventArgs(name))
Because if no one attached an handler to the event, then the PropertyChangedobject returns null. So you'll have to ensure it's not null before calling it.
因为如果没有人为事件附加处理程序,则PropertyChanged对象返回null. 所以你必须在调用它之前确保它不为空。
where does PropertyChanged get assigned?
PropertyChanged 在哪里分配?
In the "listener" classes.
在“听众”课程中。
For example, you could write in other class:
例如,您可以在其他类中编写:
ChattyClass tmp = new ChattyClass();
tmp.PropertyChanged += (sender, e) =>
{
Console.WriteLine(string.Format("Property {0} has been updated", e.PropertyName));
};
What does the assignment look like?
任务是什么样的?
In C# we use the assignment operators +=and -=for events. I recommend reading the following articleto understand how to write event handlers using the anonymous method form (example above) and the "old" form.
在 C# 中,我们使用赋值运算符+=和-=事件。我建议阅读以下文章以了解如何使用匿名方法表单(上面的示例)和“旧”表单编写事件处理程序。
回答by Paul Richards
From taking the original code, and incorporating @Styxxy 's answer, I come out with:
从获取原始代码,并结合@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);
}
}

