文章目录
相关链接
代码仓库
我为了方便展示源代码,我将代码提交到了代码仓库里面
前言
为了深入的重新学习WPF的基础知识,打算从【B站:十月的寒流】这位大佬上面去学习WPF的相关的知识。我其实更推荐大家去看原视频的相关教程内容。
环境
- visual studio 2022
- .net core 8.0
- windows11
DataGrid 数据筛选
项目配置
如何使用我这里就不展开说明了
WPF CommunityToolkit.Mvvm
WPF CommunityToolkit.Mvvm Messenger通讯
WPF-UI HandyControl 简单介绍
WPF-UI HandyControl 控件简单实战+IconPacks矢量图导入
Bogus,.NET生成批量模拟数据
使用原理
WPF DataGrid 数据过滤
ICollectionView让MVVM更简单
微软官方文档|ICollectionView 接口
这里不得不提到微软的WPF文档了,写了和没写差不多。
实现原理就是微软为了方便对数据进行分组、排序和筛选。给ItemSorce添加了ICollectionView 专门用于干这个。然后我们可以对ICollectionView添加规则,Ture就是需要,False就是不需要。
主要代码(详细代码可以看我的GitHub仓库)
Models.Person
csharp
public class Person
{
public int Id { get; set; }
public string FullName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime BirthDay { get; set; }
}
DataGirdView
xml
<UserControl x:Class="DataGrid_Filter.Views.DataGirdView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:DataGrid_Filter.Views"
xmlns:hc="https://handyorg.github.io/handycontrol"
xmlns:viewModels="clr-namespace:DataGrid_Filter.ViewModels"
mc:Ignorable="d"
d:DesignHeight="450"
d:DesignWidth="800">
<UserControl.DataContext>
<viewModels:DataGridViewModel x:Name="ViewModel" />
</UserControl.DataContext>
<DockPanel LastChildFill="True">
<StackPanel DockPanel.Dock="Bottom"
Orientation="Horizontal"
Margin="5">
<Button Command="{Binding AddItemCommand}"
Content="AddNewItem" />
<!--添加名称,方便绑定-->
<hc:TextBox Text="{Binding FilterStr,UpdateSourceTrigger=PropertyChanged}"
hc:InfoElement.Placeholder="Filter By Name"
MinWidth="200"
Margin="5 0 0 0"
x:Name="FilterBox" />
</StackPanel>
<!--添加名称,方便绑定-->
<DataGrid ItemsSource="{Binding PeopleList}"
x:Name="PeopleDataGrid">
</DataGrid>
</DockPanel>
</UserControl>
csharp
public partial class DataGirdView : UserControl
{
public DataGirdView()
{
InitializeComponent();
//将主要的代码逻辑放在ViewModel里面
ViewModel.DataGirdView = this;
}
}
DataGridViewModel
csharp
public partial class DataGridViewModel : ObservableObject
{
[ObservableProperty]
private string title = "DataGird Tttle";
[ObservableProperty]
private ObservableCollection<Models.Person> peopleList = new();
[ObservableProperty]
private ICollectionView collectionView;
[ObservableProperty]
private string filterStr = "";
private DataGrid_Filter.Views.DataGirdView dataGirdView;
public DataGrid_Filter.Views.DataGirdView DataGirdView
{
get => dataGirdView;
set {
dataGirdView = value;
ViewInit();
}
}
public static int OrderId = 1;
/// <summary>
/// 生成模拟的数据
/// </summary>
public static Faker<Models.Person> Faker = new Faker<Models.Person>()
.RuleFor(t => t.Id, f => OrderId++)
.RuleFor(t => t.FirstName, f => f.Name.FirstName())
.RuleFor(t => t.LastName, f => f.Name.LastName())
.RuleFor(t => t.FullName, f => f.Name.FullName())
.RuleFor(t => t.BirthDay, f => f.Date.Between(new DateTime(1990, 1, 1), new DateTime(2010, 1, 1)));
public DataGridViewModel()
{
PeopleList = new ObservableCollection<Models.Person>(Faker.Generate(10));
}
[RelayCommand]
public void AddItem()
{
var item = Faker.Generate();
PeopleList.Add(item);
}
public void ViewInit()
{
//获取ItemSource的CollectionView
CollectionView = CollectionViewSource.GetDefaultView(DataGirdView.PeopleDataGrid.ItemsSource);
//给CollectionView添加过滤规则
CollectionView.Filter = (item) =>
{
if (string.IsNullOrEmpty(FilterStr))
{
return true;
}
else
{
var model = item as Models.Person;
return model.FirstName.Contains(FilterStr) || model.LastName.Contains(FilterStr) || model.FullName.Contains(FilterStr);
}
};
//在TextChanged的时候,实时更新
DataGirdView.FilterBox.TextChanged += (s, e) =>
{
CollectionView.Refresh();
};
}
}
实现效果
DataGrid直接绑定CollectionView
第一种方法是通过获取ItemSorce来获取CollectionView,实在是舍近求远。这次我们选择第二种方法。直接绑定设置好的CollectionView。然后我们在每次刷新输入框和改动数据的时候,主动更新绑定内容。
xaml
xml
<UserControl x:Class="DataGrid_Filter.Views.DataGrid2View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:DataGrid_Filter.Views"
xmlns:viewModels="clr-namespace:DataGrid_Filter.ViewModels"
xmlns:hc="https://handyorg.github.io/handycontrol"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.DataContext>
<viewModels:DataGrid2ViewModel />
</UserControl.DataContext>
<Grid>
<DockPanel LastChildFill="True">
<StackPanel DockPanel.Dock="Bottom"
Orientation="Horizontal"
Margin="5">
<Button Command="{Binding AddItemCommand}"
Content="AddNewItem" />
<!--添加名称,方便绑定-->
<hc:TextBox Text="{Binding FilterStr,UpdateSourceTrigger=PropertyChanged}"
hc:InfoElement.Placeholder="Filter By Name"
MinWidth="200"
Margin="5 0 0 0"
x:Name="FilterBox" />
</StackPanel>
<!--添加名称,方便绑定-->
<DataGrid ItemsSource="{Binding CollectionView}"
x:Name="PeopleDataGrid">
</DataGrid>
</DockPanel>
</Grid>
</UserControl>
ViewModel
csharp
using Bogus;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DataGrid_Filter.Views;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
namespace DataGrid_Filter.ViewModels
{
public partial class DataGrid2ViewModel : ObservableObject
{
[ObservableProperty]
private List<Models.Person> people = new List<Models.Person>();
[ObservableProperty]
private ICollectionView collectionView;
private string filterStr = "";
public string FilterStr
{
get
{
return filterStr;
}
set
{
SetProperty(ref filterStr, value);
CollectionView.Refresh();
}
}
[RelayCommand]
public void AddItem()
{
var item = DataGridViewModel.Faker.Generate();
People.Add(item);
CollectionView.Refresh();
}
public DataGrid2ViewModel()
{
People = DataGridViewModel.Faker.Generate(10).ToList();
CollectionView = CollectionViewSource.GetDefaultView(People);
CollectionView.Filter = (item) =>
{
if (string.IsNullOrEmpty(FilterStr))
{
return true;
}
else
{
var model = item as Models.Person;
return model.FirstName.Contains(FilterStr) || model.LastName.Contains(FilterStr) || model.FullName.Contains(FilterStr);
}
};
}
}
}
总结
学WPF还是不能闭门造车,一定要先找网上有没有对应的方法,实在没有再自己想方法解决。【十月的寒流】的【WPF教程】确实不错,建议大家都去看一下。