Reputation: 2459
I have a class with several properties. When these are changed, a PropertyChangedEvent
raised. Some properties depend on other properties, so when one of the dependencies is changed, it raises a PropertyChangedEvent
for itself, and for the property that depends on it.
My problem is, that I have attached a PropertyChangedEventHandler
to an instance of this class. When one of the properties that is depended upon by another property, this event handler is called several times. Is there a way to get around this?
UPDATE
A little code, just to illustrate what I'm talking about:
private bool _foo;
private bool _bar;
public bool Foo
{
get { return _foo; }
set
{
_foo = value;
OnPropertyChanged("Foo");
OnPropertyChanged("Baz");
}
}
public bool Bar
{
get { return _bar; }
set
{
_bar = value;
OnPropertyChanged("Bar");
OnPropertyChanged("Baz");
}
}
public bool Baz
{
get
{
return Foo && Bar;
}
}
When Foo
is set, Baz
changes as well. If I attach a PropertyChangedEventHandler
, this will be called twice, when I set Foo
. I only want to call it once. Is there a nice way around it?
Upvotes: 1
Views: 3907
Reputation: 69959
All you need to do is think logically about this issue for a moment to get your answer. You have the following situation:
public bool Foo
{
get { return _foo; }
set
{
_foo = value;
OnPropertyChanged("Foo");
OnPropertyChanged("Baz");
}
}
public bool Bar
{
get { return _bar; }
set
{
_bar = value;
OnPropertyChanged("Bar");
OnPropertyChanged("Baz");
}
}
public bool Baz
{
get
{
return Foo && Bar;
}
}
My first comment is that if you are going to raise your INotifyPropertyChanged.PropertyChanged
event more than once at a time, then you'd be better off using an implementation like this, which would enable you to raise the event for as many properties as you like at once:
protected virtual void NotifyPropertyChanged(params string[] propertyNames)
{
if (PropertyChanged != null)
{
foreach (string propertyName in propertyNames)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
...
NotifyPropertyChanged("Foo", "Bar");
So back to your problem... let's think about your requirement:
Baz
changes.Its value can be changed when either the Foo
or Bar
property values change... therefore you'll need to notify the interface when either of them changes, as you have.
Now, @Franck commented to say that You should from the setter of Property 1 trigger a method to update Property 2 which by changing will trigger his own property change. Let's think about that for a minute... presumably, you'd need to call this same method from both of the Foo
or Bar
property setters to make it work.
However, what would actually happen is that the when the Foo
and Bar
values are changed, the method would be called twice and so the INotifyPropertyChanged
notification will still be called twice, albeit now coming from the Baz
setter... so clearly, this is no improvement.
There is however, one more option that could work for you. For this to work, you'd need to add a helper method that would update the Foo
or Bar
property values and notify the INotifyPropertyChanged
interface on behalf of the Baz
property:
public void UpdateBaz(bool? foo, bool? bar)
{
if (foo != null) Foo = foo;
if (bar != null) Bar = bar;
OnPropertyChanged("Baz");
}
Of course, for this to work, you'd need to remove the call to OnPropertyChanged("Baz")
from the two property handlers:
public bool Foo
{
get { return _foo; }
set { _foo = value; OnPropertyChanged("Foo"); }
}
public bool Bar
{
get { return _bar; }
set { _bar = value; OnPropertyChanged("Bar"); }
}
However, if you want the Foo
and Bar
properties to be updated through Binding
, then you'd be back to @Franck's suggestion of calling this method twice and the two properties are updated individually. In that case, it seems as though you'll just have to put up with the Baz
property being notified twice.
Upvotes: 4
Reputation: 1778
insert a value changed check in your setter like:
set
{
if(value != [yourfield])
{
yourfield = value;
OnPropertyChanged(Yourfield);
}
}
Upvotes: 1