我有一个字符串的ObservableCollection,我想把它与转换器绑定到ListBox,并只显示以某些前缀开头的字符串。
我写道:
public ObservableCollection<string> Names { get; set; }
public MainWindow()
{
InitializeComponent();
Names= new ObservableCollection<Names>();
DataContext = this;
}
和转换器:
class NamesListConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
return null;
return (value as ICollection<string>).Where((x) => x.StartsWith("A"));
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
和XAML:
<ListBox x:Name="filesList" ItemsSource="{Binding Path=Names, Converter={StaticResource NamesListConverter}}" />
但列表框在更新(添加或删除)后不会更新 我注意到,如果我从绑定中删除转换器,它的工作完美。 我的代码出了什么问题?
答案 0 :(得分:4)
您的转换器正在从原始ObservableCollection中的对象创建新集合。使用绑定设置的ItemsSource不再是原始的ObservableCollection。 为了更好地理解,这与您所写的内容相同:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
return null;
var list = (value as ICollection<string>).Where((x) => x.StartsWith("A")).ToList();
return list;
}
转换器返回的列表是新对象,包含源集合中的数据副本。原始集合中的进一步更改不会反映在该新列表中,因此ListBox不知道该更改。 如果您想过滤数据,请查看CollectionViewSource。
编辑:如何过滤
public ObservableCollection<string> Names { get; set; }
public ICollectionView View { get; set; }
public MainWindow()
{
InitializeComponent();
Names= new ObservableCollection<string>();
var viewSource = new CollectionViewSource();
viewSource.Source=Names;
//Get the ICollectionView and set Filter
View = viewSource.View;
//Filter predicat, only items that start with "A"
View.Filter = o => o.ToString().StartsWith("A");
DataContext=this;
}
在XAML中,将ItemsSource设置为CollectionView
<ListBox x:Name="filesList" ItemsSource="{Binding Path=View}"/>
答案 1 :(得分:1)
添加或删除元素时可能不使用转换器。实现所需内容的最简单方法可能是在类中实现INotifyPropertyChanged,并在每次添加或删除项时触发PropertyChanged事件。
一般来说,“正确”的方式是使用CollectionView
。