WPF binding ObservableCollection with converter

会有一股神秘感。 提交于 2019-12-23 04:27:03

问题


I have an ObservableCollection of strings and I'm tring to bind it with converter to ListBox and show only the strings that start with some prefix.
I wrote:

public ObservableCollection<string> Names { get; set; }

public MainWindow()
{
    InitializeComponent();
    Names= new ObservableCollection<Names>();
    DataContext = this;
}

and the converter:

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;
    }
}

and the XAML:

<ListBox x:Name="filesList" ItemsSource="{Binding Path=Names, Converter={StaticResource NamesListConverter}}" />

but the listbox do not update after its beed update (add or remove).
I have notice that if I removes the converter from the binding its works perfectly. What is wrong with my code?


回答1:


Your converter is creating new collection from objects in the original ObservableCollection. The ItemsSource that is set using your binding is no longer the original ObservableCollection. To understand better, this is equal to what you have wrote:

 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;
   }

The list that converter is returning is new object with copy of data from source collection. Further changes in original collection are not reflected in that new list so the ListBox does not know about that changes. If you want to filter your data take a look into CollectionViewSource.

EDIT: How to filter

     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;
    }

In the XAML set the ItemsSource to the CollectionView

<ListBox x:Name="filesList" ItemsSource="{Binding Path=View}"/>



回答2:


Probably the converter isn't used when you add or remove elements. The simplest way to achieve what you want may be to implement INotifyPropertyChanged in your class and fire the PropertyChanged event everytime you add or remove items. In general the "correct" way would be to use a CollectionView.



来源:https://stackoverflow.com/questions/16372822/wpf-binding-observablecollection-with-converter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!