我有一个有几个属性的类。当这些被更改时,PropertyChangedEvent
被提升。某些属性依赖于其他属性,因此当其中一个依赖项发生更改时,它会为自身以及依赖于它的属性引发PropertyChangedEvent
。
我的问题是,我已将PropertyChangedEventHandler
附加到此类的实例。当其中一个属性依赖于另一个属性时,将多次调用此事件处理程序。有办法解决这个问题吗?
更新
一些小代码,只是为了说明我在谈论的内容:
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;
}
}
设置Foo
后,Baz
也会发生变化。如果我附加PropertyChangedEventHandler
,则在设置Foo
时会调用两次。我只想打电话一次。周围有一个很好的方法吗?
答案 0 :(得分:4)
您需要做的就是从逻辑上思考这个问题片刻以获得答案。您有以下情况:
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;
}
}
我的第一个评论是,如果 一次多次提升INotifyPropertyChanged.PropertyChanged
事件,那么你最好使用这样的实现,使您能够立即为任意数量的属性引发事件:
protected virtual void NotifyPropertyChanged(params string[] propertyNames)
{
if (PropertyChanged != null)
{
foreach (string propertyName in propertyNames)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
...
NotifyPropertyChanged("Foo", "Bar");
回到你的问题......让我们考虑你的要求:
Baz
的值发生变化时,您需要通知界面。当Foo
或Bar
属性值发生更改时,可以更改其值...因此,您需要在其中任何一个更改时通知接口,如您所知。
现在,@ Franck评论说你应该从属性1的setter触发一个更新属性2的方法,通过更改将触发他自己的属性更改。让我们考虑一下......大概,您需要从Foo
或Bar
属性设置器中调用相同的方法才能使其正常工作。
然而,实际发生的是,当Foo
和Bar
值发生更改时,该方法将被调用两次,因此INotifyPropertyChanged
通知仍会被调用两次,虽然现在来自Baz
制定者......但很明显,这并没有改善。
然而,还有一个选项对您有用。为此,您需要添加一个帮助方法来更新Foo
或Bar
属性值和代表INotifyPropertyChanged
接口通知Baz
public void UpdateBaz(bool? foo, bool? bar)
{
if (foo != null) Foo = foo;
if (bar != null) Bar = bar;
OnPropertyChanged("Baz");
}
属性:
OnPropertyChanged("Baz")
当然,为了实现这一目标,您需要从两个属性处理程序中删除对public bool Foo
{
get { return _foo; }
set { _foo = value; OnPropertyChanged("Foo"); }
}
public bool Bar
{
get { return _bar; }
set { _bar = value; OnPropertyChanged("Bar"); }
}
的调用:
Foo
但是,如果您想通过Bar
更新Binding
和Baz
属性,那么您将回到@Franck关于调用此方法两次和两个属性的建议单独更新。在这种情况下,似乎你只需要忍受两次通知的{{1}}财产。
答案 1 :(得分:0)
在您的setter中插入一个值已更改的检查,如:
set
{
if(value != [yourfield])
{
yourfield = value;
OnPropertyChanged(Yourfield);
}
}