c# - 需要使用 C# 中的文本框对我的 WPF Datagrid 实现过滤器
问题描述
我有一个 WPF 数据网格,我在其中使用 itemsource 填充数据表中的数据。现在我想为我的 Datagrid 应用文本框过滤器或(如果可能,将过滤器应用到列标题)。我对 WPF 很陌生,所以任何人都可以帮我解决这个问题。
注意:我没有使用 MVVM,我只是使用简单的 WPF 数据网格
Currently my code is like below:
XAML Code:
-------------------
<Page.Resources>
<LinearGradientBrush x:Key="HeaderBrush" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#FF6B6EB9" Offset="0"/>
<GradientStop Color="#FF6B6EB9" Offset="1"/>
<GradientStop Color="#FF6B6EB9" Offset="0.509"/>
<GradientStop Color="#FF6B6EB9" Offset="0.542"/>
<GradientStop Color="#FF6B6EB9" Offset="0.542"/>
<GradientStop Color="#FF9699DC" Offset="0.904"/>
</LinearGradientBrush>
<LinearGradientBrush x:Key="HeaderBorderBrush" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#FF1060D1" Offset="0.614"/>
<GradientStop Color="#FF316BD5" Offset="0.853"/>
<GradientStop Color="#FFBBD3ED" Offset="1"/>
</LinearGradientBrush>
<Style x:Key="HeaderStyle" TargetType="DataGridColumnHeader">
<Setter Property="Background" Value="{StaticResource HeaderBrush}" />
<Setter Property="Foreground" Value="White" />
<Setter Property="BorderBrush" Value="{StaticResource HeaderBorderBrush}" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="MinWidth" Value="0" />
<Setter Property="MinHeight" Value="30" />
<Setter Property="Cursor" Value="Hand" />
</Style>
</Page.Resources>
<Grid>
<DataGrid Name="dgExcel" LoadingRow="dgExcel_LoadingRow" RowEditEnding="dgExcel_RowEditEnding" ColumnHeaderStyle="{StaticResource HeaderStyle}" CanUserDeleteRows="True" AutoGenerateColumns="True" AutoGeneratingColumn="dgExcel_AutoGeneratingColumn" ItemsSource = "{Binding}" ColumnWidth="Auto" SelectionChanged="dgExcel_SelectionChanged" CanUserAddRows="True" Loaded="dgExcel_Loaded" CellEditEnding="dgExcel_CellEditEnding" ScrollViewer.CanContentScroll="True" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" GridLinesVisibility="Horizontal" AlternatingRowBackground="#FFF3F3F3">
</DataGrid>
</Grid>
用于加载 wpf 数据网格的代码文件:
private void dgExcel_Loaded(object sender, RoutedEventArgs e)
{
string ConeectionString = String.Format(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source='C:\\Test.xlsx';" + "Extended Properties=\"Excel 12.0 Xml;HDR=YES\"");
OleDbConnection oconn = new OleDbConnection(ConeectionString);
System.Data.DataSet DtSet;
System.Data.OleDb.OleDbDataAdapter MyCommand;
MyCommand = new System.Data.OleDb.OleDbDataAdapter("select * from [Sheet1$]", oconn);
MyCommand.TableMappings.Add("Table", "TestTable");
DtSet = new System.Data.DataSet();
MyCommand.Fill(DtSet);
dgExcel.DataContext = DtSet.Tables[0];
System.Data.DataTable dt = new System.Data.DataTable();
//actionsGrid.ItemsSource = DtSet.DefaultViewManager;
dt = DtSet.Tables[0];
dgExcel.ItemsSource = dt.DefaultView;
oconn.Close();
}
解决方案
首先,添加一个文本框。您可以找到带有按钮的更高级的文本框来清除文本,或者主动点击按钮进行搜索,但现在只是一个简单的文本框。确保它被命名,并添加一个TextChanged
事件处理程序。
<TextBox x:Name="searchBox" TextChanged="SearchTextBox_TextChanged"/>
然后,您想要连接到您的CollectionView
. 您可以直接分配它,或者使用CollectionViewSource
XAML 代码中的元素。这是一个基本版本:
<Window.Resources>
<CollectionViewSource x:Key="collectionView" Source="{Binding OrderCollection}"
Filter="CollectionViewSource_Filter"/>
</Window.Resources>
这假设ObservableCollection
已经在代码后面或视图模型中设置了一个。
public ObservableCollection<Orders> OrderCollection { get; } = //collection of orders
然后DataGrid
'sItemSource
将指向'CollectionViewSource
作为静态资源绑定。还有其他方法可以构建它(例如,直接连接到dt.DefaultView
),但我将把它留给您配置。
在TextBox
您想要刷新视图的文本更改事件处理程序中,每次用户输入新字符时,它都会重新评估过滤器:
private void SearchTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
RefreshView();
}
void RefreshView()
{
var viewSource = (CollectionViewSource)Resources["collectionView"];
viewSource?.View?.Refresh();
}
警告:这不会处理粘贴的文本。为此有一组单独的事件。
当视图刷新时,它将ItemsSource
通过Filter
集合视图运行各个项目。然后只需设置是否接受每个项目。
private void CollectionViewSource_Filter(object sender, FilterEventArgs e)
{
if (e.Item is DataRow row)
{
if (searchBox.HasText)
{
e.Accepted = Filter(row, searchBox.Text);
}
else
{
e.Accepted = true;
}
}
else
{
e.Accepted = false;
}
}
private bool Filter(DataRow row, string filterText)
{
// check if row matches the filterText
// check whichever columns of the row are appropriate
return true;
}
这些东西可以通过不同的方式连接在一起,但这应该涵盖基本必需品。我没有检查我期望您的数据的数据类型是通过事件处理程序传递的实际数据类型,因此请务必仔细检查。
推荐阅读
- elasticsearch - 从三台服务器创建 Elasticsearch 集群
- react-native - 在 react-navigation cardOverlays 上注册按下(以关闭模式)
- python - SageMaker 批量转换不断失败
- python - Tensorflow MCMC 不会演化链状态
- python - 格式化 Python Fabric 输出
- excel - Excel与索引/匹配最接近的匹配
- powershell - 如何优化跨所有域控制器的查询以找到最新的登录日期?
- security - 使用 Ory/Kratos 登录/注册 API 流程
- javascript - JavaScript:在给定索引列表的多维数组中获取元素
- flutter - Flutter 使用 path_provider 包获取外部存储目录和 MediaStore