WPF 使用ICollectionView过滤表格数据
ICollectionView接口
是一个用于提供数据视图的类,它允许你对数据进行排序、筛选和分组。可以通过静态方法CollectionViewSource.GetDefaultView(object)获取。
代码演示
MVVM框架使用CommunityToolkit.MVVM,UI界面框架使用MaterialDesignThemes,生成测试数据使用Bogus
View代码为:
<Window
x:Class="WPFTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:be="http://schemas.microsoft.com/xaml/behaviors"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPFTest"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow"
Width="800"
Height="450"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox
Grid.Row="0"
Margin="5"
Text="{Binding SearchContent, UpdateSourceTrigger=PropertyChanged}" />
<DataGrid
x:Name="DataGrid"
Grid.Row="1"
Margin="5"
materialDesign:DataGridAssist.CellPadding="4 2 2 2"
materialDesign:DataGridAssist.ColumnHeaderPadding="4 2 2 2"
AutoGenerateColumns="True"
Background="White"
GridLinesVisibility="All"
HorizontalScrollBarVisibility="Visible"
IsReadOnly="True"
ItemsSource="{Binding CollectionView}"
SelectionMode="Single"
VerticalScrollBarVisibility="Visible">
</DataGrid>
</Grid>
</Window>
ViewModel部分代码为:
using CommunityToolkit.Mvvm.ComponentModel;
using Bogus;
using System.ComponentModel;
using System.Windows.Data;
namespace WPFTest
{
public class MainViewModel : ObservableRecipient
{
private List<DataModel> list = new List<DataModel>();
//数据表格显示内容,动态加载不同类型的内容
private ICollectionView collectionView;
public ICollectionView CollectionView
{
get => collectionView;
set => SetProperty(ref collectionView, value);
}
//搜索内容
private string searchContent = string.Empty;
public string SearchContent
{
get => searchContent;
set
{
if (SetProperty(ref searchContent, value))
{
CollectionView.Refresh();
}
}
}
public MainViewModel()
{
InitTestData();
CollectionView = CollectionViewSource.GetDefaultView(list);
CollectionView.Filter = new Predicate<object>(OnFilterMovie);
}
/// <summary>
/// 过滤方法
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
private bool OnFilterMovie(object item)
{
if (string.IsNullOrEmpty(SearchContent) || item == null || list == null || list.Count <= 0)
{
return true;
}
else
{
DataModel model = item as DataModel;
return model.Name.IndexOf(SearchContent, StringComparison.InvariantCultureIgnoreCase) >= 0;
}
}
private void InitTestData()
{
list.Clear();
Randomizer.Seed = new Random(123456);
var customerGenerator = new Faker<DataModel>()
.RuleFor(c => c.Id, Guid.NewGuid())
.RuleFor(c => c.Name, f => f.Company.CompanyName())
.RuleFor(c => c.Address, f => f.Address.FullAddress())
.RuleFor(c => c.City, f => f.Address.City())
.RuleFor(c => c.Country, f => f.Address.Country())
.RuleFor(c => c.ZipCode, f => f.Address.ZipCode())
.RuleFor(c => c.Phone, f => f.Phone.PhoneNumber())
.RuleFor(c => c.Email, f => f.Internet.Email());
list = customerGenerator.Generate(100);
}
}
}
Model代码为:
namespace WPFTest
{
public class DataModel
{
public Guid Id { get; set; } = new Guid();
public string Name { get; set; } = string.Empty;
public string Address { get; set; } = string.Empty;
public string City { get; set; } = string.Empty;
public string Country { get; set; } = string.Empty;
public string ZipCode { get; set; } = string.Empty;
public string Phone { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
}
}
示例程序界面由文本框和表格组成,文本框过滤名称,后台绑定数据一发生变化则刷新CollectionView更新界面,表格实际绑定为CollectionView,数据部分可以直接用List而不用ObservableCollection,过滤方法为
CollectionView.Filter = new Predicate<object>(OnFilterMovie);
将过滤逻辑OnFilterMovie绑定至Filter上,在OnFilterMovie中判断实际的返回结果
运行效果如下:
回顾
CollectionView就是一个视图类,它的实例代表了一个视图类实例,视图可以用来做集合对象显示的相关操作(分组,排序,过滤,导航等)。视图的优点有:对视图的分组,过滤等等操作不会影响到源集合本身;一个集合可以有多个不同的视图,源集合的改变有能力通知到它所有的视图(前提是源集合实现了INotifyCollectionChanged接口)。