WPF 将 ObservableCollection 与转换器绑定

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16372822/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 08:43:35  来源:igfitidea点击:

WPF binding ObservableCollection with converter

c#wpfdata-bindingobservablecollection

提问by user2348001

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:

我有一个 ObservableCollection 字符串,我想将它与转换器绑定到 ListBox 并仅显示以某些前缀开头的字符串。
我写:

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:

和 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?

但列表框在更新(添加或删除)后不会更新。
我注意到,如果我从绑定中移除转换器,它的工作原理是完美的。我的代码有什么问题?

回答by jure

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:

您的转换器正在从原始 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;
   }

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.

转换器返回的列表是带有源集合中数据副本的新对象。原始集合中的进一步更改不会反映在该新列表中,因此 ListBox 不知道这些更改。如果您想过滤数据,请查看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

在 XAML 中,将 ItemsSource 设置为 CollectionView

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

回答by JeffRSon

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.

添加或删除元素时,可能没有使用转换器。实现您想要的最简单的方法可能是在您的类中实现 INotifyPropertyChanged 并在每次添加或删除项目时触发 PropertyChanged 事件。一般来说,“正确”的方法是使用CollectionView.