Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf CollectionViewSource上的触发器筛选器_Wpf_Xaml_Mvvm_Filter_Collectionviewsource - Fatal编程技术网

Wpf CollectionViewSource上的触发器筛选器

Wpf CollectionViewSource上的触发器筛选器,wpf,xaml,mvvm,filter,collectionviewsource,Wpf,Xaml,Mvvm,Filter,Collectionviewsource,我正在使用MVVM模式开发WPF桌面应用程序 我试图根据在文本框中键入的文本,从列表视图中筛选出一些项目。我希望在更改文本时过滤列表视图项 我想知道当筛选器文本更改时如何触发筛选器。 ListView绑定到一个CollectionViewSource,它绑定到我的ViewModel上的observeCollection。过滤器文本的TextBox绑定到ViewModel上的一个字符串,并按原样使用UpdateSourceTrigger=PropertyChanged <Collection

我正在使用MVVM模式开发WPF桌面应用程序

我试图根据在
文本框中键入的文本,从
列表视图中筛选出一些项目。我希望在更改文本时过滤
列表视图

我想知道当筛选器文本更改时如何触发筛选器。

ListView
绑定到一个
CollectionViewSource
,它绑定到我的ViewModel上的
observeCollection
。过滤器文本的
TextBox
绑定到ViewModel上的一个字符串,并按原样使用
UpdateSourceTrigger=PropertyChanged

<CollectionViewSource x:Key="ProjectsCollection"
                      Source="{Binding Path=AllProjects}"
                      Filter="CollectionViewSource_Filter" />

<TextBox Text="{Binding Path=FilterText, UpdateSourceTrigger=PropertyChanged}" />

<ListView DataContext="{StaticResource ProjectsCollection}"
          ItemsSource="{Binding}" />

Filter=“CollectionViewSource\u Filter”
链接到代码隐藏中的事件处理程序,它只调用ViewModel上的筛选器方法

过滤在FilterText的值更改时完成-FilterText属性的设置程序调用FilterList方法,该方法迭代my ViewModel中的
ObservableCollection
,并在每个项ViewModel上设置
boolean
FilteredOut属性

我知道FilteredOut属性会在过滤器文本更改时更新,但列表不会刷新。
CollectionViewSource
filter事件只有在我重新加载UserControl时才会被触发,方法是先离开它,然后再返回

更新过滤器信息后,我尝试调用OnPropertyChanged(“AllProjects”)
,但没有解决我的问题。 (“AllProjects”是我的ViewModel上的
ObservableCollection
属性,
CollectionViewSource
绑定到该属性。)

当FilterText
TextBox
的值更改时,如何使
CollectionViewSource
重新过滤自身


如果我能很好地理解你的问题,我将非常感谢:


FilterText
属性的设置部分,只需调用
Refresh()
CollectionView

也许您在问题中简化了视图,但如前所述,您并不真正需要CollectionViewSource-您可以直接绑定到ViewModel中的筛选列表(mItemsToFilter是正在筛选的集合,在您的示例中可能是“AllProjects”):

public ReadOnlyObservableCollection AllFilteredItems
{
得到
{ 
if(String.IsNullOrEmpty(mFilterText))
返回新的ReadOnlyObservableCollection(mItemsToFilter);
var filtered=mItemsToFilter.Where(item=>item.Text.Contains(mFilterText));
返回新的ReadOnlyObservableCollection(
新的可观察收集(过滤);
}
}
公共字符串筛选器文本
{
获取{return mFilterText;}
设置
{ 
mFilterText=值;
if(PropertyChanged!=null)
{
PropertyChanged(这是新的PropertyChangedEventArgs(“FilterText”);
PropertyChanged(即新PropertyChangedEventArgs(“AllFilteredItems”);
}
}
}
你的观点就是:

<TextBox Text="{Binding Path=FilterText,UpdateSourceTrigger=PropertyChanged}" />
<ListView ItemsSource="{Binding AllFilteredItems}" />

一些简要说明:

  • 这消除了代码隐藏中的事件

  • 它还消除了“FilterOut”属性,这是一个人工的、仅GUI的属性,因此实际上破坏了MVVM。除非您计划序列化它,否则我不希望它出现在我的ViewModel中,当然也不希望出现在我的模型中

  • 在我的示例中,我使用“Filter In”而不是“Filter Out”。在大多数情况下,我应用的筛选器是我确实希望看到的内容,这似乎更符合逻辑。如果确实要筛选内容,只需否定Contains子句(即item=>!item.Text.Contains(…))

  • 您可能有一种更集中的方式在ViewModel中进行设置。需要记住的重要一点是,当您更改FilterText时,还需要通知您的AllFilteredItems集合。我在这里内联完成了此操作,但您也可以处理PropertyChanged事件,并在e.PropertyName为FilterText时调用PropertyChanged。


如果需要任何澄清,请告诉我。

不要在视图中创建
CollectionViewSource
。而是在视图模型中创建类型为
ICollectionView
的属性,并将
ListView.ItemsSource
绑定到该属性

完成此操作后,可以将逻辑放入
FilterText
属性的setter中,每当用户更改它时,该属性就会调用
ICollectionView
上的
Refresh()

您会发现这也简化了排序问题:您可以将排序逻辑构建到视图模型中,然后公开视图可以使用的命令

编辑

下面是一个使用MVVM对集合视图进行动态排序和筛选的非常简单的演示。这个演示没有实现
FilterText
,但是一旦您了解了它的工作原理,您应该不会在实现
FilterText
属性和使用该属性而不是硬编码属性的谓词时遇到任何困难它正在使用的过滤器

(还要注意,这里的视图模型类没有实现属性更改通知。这只是为了保持代码简单:由于此演示中没有任何内容实际更改属性值,因此不需要属性更改通知。)

首先为您的项目创建一个类:

公共类ItemViewModel
{
公共字符串名称{get;set;}
公共整数{get;set;}
}
现在是应用程序的视图模型。这里有三件事:首先,它创建并填充自己的
ICollectionView
;其次,它公开
ApplicationCommand
(见下文)视图将使用它来执行排序和筛选命令,最后,它实现了对视图进行排序或筛选的
execute
方法:

公共类应用程序视图模型
{
公共应用程序视图模型()
{
Items.Add(新建ItemViewMo)
<TextBox Text="{Binding Path=FilterText,UpdateSourceTrigger=PropertyChanged}" />
<ListView ItemsSource="{Binding AllFilteredItems}" />
ItemsSource={Binding Path=YourCollectionViewSourceProperty}
ItemsSource={Binding Path=YourCollectionViewSourceProperty.View}    
  <CollectionViewSource
         Source="{Binding Items}"
         Filter="FilterPredicateFunction"
         IsLiveFilteringRequested="True">
    <CollectionViewSource.LiveFilteringProperties>
      <system:String>FilteredProperty1</system:String>
      <system:String>FilteredProperty2</system:String>
    </CollectionViewSource.LiveFilteringProperties>
  </CollectionViewSource>
CollectionViewSource.View.Refresh();