首页 > 解决方案 > 需要使用 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();
        }

标签: c#filterdatagrid

解决方案


首先,添加一个文本框。您可以找到带有按钮的更高级的文本框来清除文本,或者主动点击按钮进行搜索,但现在只是一个简单的文本框。确保它被命名,并添加一个TextChanged事件处理程序。

<TextBox x:Name="searchBox" TextChanged="SearchTextBox_TextChanged"/>

然后,您想要连接到您的CollectionView. 您可以直接分配它,或者使用CollectionViewSourceXAML 代码中的元素。这是一个基本版本:

<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;
}

这些东西可以通过不同的方式连接在一起,但这应该涵盖基本必需品。我没有检查我期望您的数据的数据类型是通过事件处理程序传递的实际数据类型,因此请务必仔细检查。


推荐阅读