WPF中ListBox控件的ItemsSource动态过滤

4

我希望通过数据源实现UI虚拟化。

我的想法是“过滤”我发送到UI的内容(在我的情况下是一个列表框)。

我注意到ItemsSource(一个可观察集合)只读一次,而更改Filter不会触发刷新...

我不明白为什么 谢谢 Jonathan


我将尝试更清楚:

我有CollectionViewSource:

<CollectionViewSource x:Key="MyItemView"
                                  Source="{Binding Path=Model.CurrentItem}" />

然后在我的ListBox中使用这个数据源:
<ListBox x:Name="myListBox"
                 ItemsSource="{Binding Source={StaticResource MyItemView}}"

我想实现一个转换器,它会返回一个过滤后的集合(基于当前日期):
<ListBox x:Name="myListBox"
                 ItemsSource="{Binding Source={StaticResource MyItemView}, Converter={StaticResource FilterByTime}, ConverterParameter=CurrentDate }"

我是这样实现的:

public class FilterByTimeConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value != null)
            {
                System.Windows.Data.ListCollectionView list = value as System.Windows.Data.ListCollectionView;

                var model = DI.Resolve<ApplicationModel>();

                list.Filter = delegate(object item) 
                { 
                    bool r= (((MyModel)item).OriginalDate > model.TimeLine.CurrentDate.AddMonths(-1) 
                        && (((MyModel)item).OriginalDate < model.TimeLine.CurrentDate.AddMonths(1)));

                   // Console.WriteLine ("{0}<{1}<{2} : {3}",model.MyListBox.CurrentDate.AddMonths(-1),((MyModel)item).OriginalDate ,model. MyListBox.CurrentDate.AddMonths(1),r.ToString());
                    return r;
                };

                return list;
            }

            return DependencyProperty.UnsetValue;
        }

这个代码可以正常工作...但只有在第一次绑定时。 当当前日期被改变并且筛选器被改变时,列表不会更新。

也许我应该监听CurrentDate属性的变化,但是我不知道如何做到这一点。

谢谢 Jonathan


请澄清您的问题。是哪个过滤器?这是您定义的属性吗? - Kent Boogaart
4个回答

9
< p > CollectionViewSource 本身支持通过其 Filter 属性进行筛选。为什么不将您的筛选逻辑放在那里呢?


6

我遇到了类似的问题,但我找到了以下解决方案:

假设下拉框显示作者列表,列表框显示所有图书,我想通过选择的作者来过滤图书或显示所有未经过滤的图书。

相关的窗口XAML片段:

<ComboBox ItemsSource="{Binding Authors}"  DisplayMemberPath="FullName" SelectedValue="{Binding FilterAuthorBy, Mode=TwoWay}" />
<ListBox Name="bookList" ItemsSource="{Binding Books}"/>

在 window 构造函数上进行绑定的方法如下:

DataContext = new BookViewModel(this);

视图模型定义如下:

public class BookViewModel
{
   private Author _filterAuthorBy;

   public BookViewModel(IBookView view)
   {
      ...
      _books = new CollectionViewSource();
      _books.Source = _bookRepository.FindAll().ToArray();
      _books.Filter += (sender, e) =>
                         {
                             Book book = e.Item as Book;
                             if (_filterAuthorBy == null)
                             {
                                 e.Accepted = true;
                             }
                             else
                             {
                                 e.Accepted = book.Authors.Contains(_filterAuthorBy);
                             }
                         };
   }

   public CollectionView Books
   {
       get
       {               
           return _books.View;
       }
   }

   public ObservableCollection<Author> Authors
   {
      get
      {
         return new ObservableCollection<Author>(_bookRepository.FindAllAuthors());
      }
   }

   public Author FilterAuthorBy
   {
       get
       {
           return _filterAuthorBy;
       }
       set
       {
           _filterAuthorBy = value;
           _books.View.Refresh();
       }
    } 
}

所选作者会传递给ViewModel,并通过调用collectionViewSource.View.Refresh()更新列表框。

4

您可能需要手动刷新:

currentViewSource.View.Refresh()

0
你在谈论哪个筛选器?如果你是CollectionView,然后将其绑定到那里,那么控件就不会有任何变化来捕捉。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接