我有一个转换器接受ObservableCollection
作为参数,并且我想在集合中任何项目的特定属性发生更改时重新评估它
例如:假设我已经使用转换器将标签绑定到Person
个对象的集合。转换器的工作是计算列表中女性的人数,并返回"有效"为1女性或"接受"对于2.我希望在任何Gender
对象的Person
属性发生更改时,都可以再次调用转换器。
我该如何做到这一点?
答案 0 :(得分:3)
如果你足够长时间玩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。
答案 1 :(得分:0)
只有在集合中添加或删除项目时才会抛出CollectionChanged事件(而不是在集合中的项目发生更改时)。因此,在更改项目时不会调用转换器。
一种选择:
在Gender属性集中包含用于评估集合的逻辑,并设置将标签绑定到的字符串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);
};
}
}