C# ListBox ItemsSource 动态过滤器 WPF
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/435003/
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
ListBox ItemsSource dynamic filter WPF
提问by
I want to make a UI virtualization via the datasource.
我想通过数据源进行 UI 虚拟化。
The idea is to "Filter" what i send to the UI (a listbox in my case).
这个想法是“过滤”我发送到用户界面的内容(在我的例子中是一个列表框)。
I noticed that the ItemsSource (an observable collection) is read once and that changing the Filter does not trigger refreshing...
我注意到 ItemsSource(一个可观察的集合)被读取一次并且更改过滤器不会触发刷新......
I don't understand why Thanks Jonathan
我不明白为什么谢谢乔纳森
I'll try to be more clear :
我会尽量说得更清楚:
I have CollectionViewSource:
我有 CollectionViewSource:
<CollectionViewSource x:Key="MyItemView"
Source="{Binding Path=Model.CurrentItem}" />
Then use this datasource in my ListBox:
然后在我的列表框中使用这个数据源:
<ListBox x:Name="myListBox"
ItemsSource="{Binding Source={StaticResource MyItemView}}"
I thought to implement a converter that would return a filtered collection (base on the current date):
我想实现一个转换器,它会返回一个过滤的集合(基于当前日期):
<ListBox x:Name="myListBox"
ItemsSource="{Binding Source={StaticResource MyItemView}, Converter={StaticResource FilterByTime}, ConverterParameter=CurrentDate }"
Which i implemented this way:
我是这样实现的:
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;
}
This works fine...but only when bounf the first time. When the Current Date is changed and that the filter is changed, the list is not updated.
这工作正常......但仅当第一次 bounf 时。当当前日期更改且过滤器更改时,列表不会更新。
Perhaps i should listen to the CurrentDate PropertyChange, but i'm confused how to do this
也许我应该听听 CurrentDate PropertyChange,但我很困惑如何做到这一点
Thanks Jonathan
谢谢乔纳森
回答by Steven Robbins
What filter are you talking about? If you are a CollectionView and then binding to that then there won't be a changed even for the control to pick up on.
你说的是什么过滤器?如果你是一个 CollectionView 然后绑定到它,那么即使控件被接收也不会发生变化。
回答by Kent Boogaart
The CollectionViewSource
itself supports filtering via its Filter
property. Why don't you put your filtering logic in there?
的CollectionViewSource
本身支持通过其过滤Filter
性质。你为什么不把你的过滤逻辑放在那里?
回答by Arcturus
You might want to manually refresh:
您可能需要手动刷新:
currentViewSource.View.Refresh()
回答by Arunas
Well, I had similar issue, but came with the following solution that works for me:
好吧,我遇到了类似的问题,但提供了以下对我有用的解决方案:
Supposedly, the combobox shows the list of authors and the listbox all books and I want to filter the books by selected author or show all books unfiltered.
据说,组合框显示作者列表和列表框所有书籍,我想按选定的作者过滤书籍或显示所有未过滤的书籍。
The pertinent window XAML fragment:
相关的窗口 XAML 片段:
<ComboBox ItemsSource="{Binding Authors}" DisplayMemberPath="FullName" SelectedValue="{Binding FilterAuthorBy, Mode=TwoWay}" />
<ListBox Name="bookList" ItemsSource="{Binding Books}"/>
Binding itself is done like this on the window constructor:
绑定本身在窗口构造函数上是这样完成的:
DataContext = new BookViewModel(this);
And the view model is defined as such:
视图模型定义如下:
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();
}
}
}
The selected author is passed down to the ViewModel and the listbox is updated by calling collectionViewSource.View.Refresh()
选定的作者被传递到 ViewModel 并通过调用 collectionViewSource.View.Refresh() 更新列表框