我有一个接受 aObservableCollection
作为参数的转换器,每当集合中任何项目的特定属性发生变化时,我都想重新评估它
例如:假设我已经Person
使用转换器将标签绑定到对象集合。转换器的工作是计算列表中女性的人数,并为 1 位女性返回“有效”或为 2 位女性返回“接受”。我希望转换器在任何时候再次调用Gender
任何Person
对象上的属性变了。
我怎样才能做到这一点?
我有一个接受 aObservableCollection
作为参数的转换器,每当集合中任何项目的特定属性发生变化时,我都想重新评估它
例如:假设我已经Person
使用转换器将标签绑定到对象集合。转换器的工作是计算列表中女性的人数,并为 1 位女性返回“有效”或为 2 位女性返回“接受”。我希望转换器在任何时候再次调用Gender
任何Person
对象上的属性变了。
我怎样才能做到这一点?
如果您在 WPF 上玩的时间足够长,那么您最终会遇到的经典问题。
我尝试了各种解决方案,但效果最好的一个是使用 BindingList ,如下所示:
public class WorldViewModel : INotifyPropertyChanged
{
private BindingList<Person> m_People;
public BindingList<Person> People
{
get { return m_People; }
set
{
if(value != m_People)
{
m_People = value;
if(m_People != null)
{
m_People.ListChanged += delegate(object sender, ListChangedEventArgs args)
{
OnPeopleListChanged(this);
};
}
RaisePropertyChanged("People");
}
}
}
private static void OnPeopleListChanged(WorldViewModel vm)
{
vm.RaisePropertyChanged("People");
}
public event PropertyChangedEventHandler PropertyChanged;
void RaisePropertyChanged(String prop)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(prop));
}
}
}
然后就像使用 ObservableCollection 一样绑定到 People 集合,除了绑定将在其项目中的任何属性更改时重新评估。
另外,请注意 OnPeopleListChanged 是静态的,因此没有内存泄漏。
Person 应该实现 INotifyPropertyChanged。
仅当从集合中添加或删除项目时(而不是更改集合中的项目),才会引发 CollectionChanged 事件。因此,更改项目时不会调用转换器。
一种选择:
在 Gender Property Set 中包含评估集合的逻辑并设置您将标签绑定到的字符串 Property。
写了狒狒答案的通用版本
public class ObservalbeList<T>: INotifyPropertyChanged
{
private BindingList<T> ts = new BindingList<T>();
public event PropertyChangedEventHandler PropertyChanged;
// This method is called by the Set accessor of each property.
// The CallerMemberName attribute that is applied to the optional propertyName
// parameter causes the property name of the caller to be substituted as an argument.
private void NotifyPropertyChanged( String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public BindingList<T> Ts
{
get { return ts; }
set
{
if (value != ts)
{
Ts = value;
if (Ts != null)
{
ts.ListChanged += delegate(object sender, ListChangedEventArgs args)
{
OnListChanged(this);
};
}
NotifyPropertyChanged("Ts");
}
}
}
private static void OnListChanged(ObservalbeList<T> vm)
{
vm.NotifyPropertyChanged("Ts");
}
public ObservalbeList()
{
ts.ListChanged += delegate(object sender, ListChangedEventArgs args)
{
OnListChanged(this);
};
}
}