使用文本框在数据网格中进行实时筛选

本文关键字:实时 筛选 网格 数据网 文本 数据 | 更新日期: 2023-09-27 18:32:09

我有一个文本框和一个DataGrid。当我在文本框中键入内容时,我想在 DataGrid 中筛选数据。

我已经用下面提到的代码完成了:

在 XAML 中:

<CollectionViewSource x:Key="GroupsViewSource" Source="{Binding Groups, UpdateSourceTrigger=PropertyChanged}" Filter="CollectionViewSource_Filter">
    <CollectionViewSource.SortDescriptions>
        <scm:SortDescription PropertyName="GroupName"/>
    </CollectionViewSource.SortDescriptions>
</CollectionViewSource>
<DataGrid Grid.Row="5" Grid.Column="1" ItemsSource="{Binding Source={StaticResource GroupsViewSource}}" 
          SelectedItem="{Binding SelectedGroup}" 
          AutoGenerateColumns="False" CanUserAddRows="False"
          SelectionMode="Single" SelectionUnit="FullRow" 
          EnableRowVirtualization="False" VirtualizingPanel.IsContainerVirtualizable="False" RowEditEnding="DataGrid_RowEditEnding">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Group Name" Width="*" SortMemberPath="GroupName">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding GroupName}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <TextBox Text="{Binding GroupName}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Parent Group" Width="*" SortMemberPath="ParentID">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding ParentID, Converter={StaticResource parentIDToGroupNameConverter}}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
            <DataGridTemplateColumn.CellEditingTemplate>
                <DataTemplate>
                    <ComboBox ItemsSource="{Binding Source={StaticResource ParentGroupsViewSource}}" 
                              DisplayMemberPath="GroupName"
                              SelectedValue="{Binding ParentID, Converter={StaticResource parentIDToGroupNameConverter}}" SelectedValuePath="GroupName"/>
                </DataTemplate>
            </DataGridTemplateColumn.CellEditingTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Edit" Width="50" IsReadOnly="True">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        <Button x:Name="btnEdit" Style="{StaticResource ResourceKey=EditButton}" Height="35" Width="35" 
                                Visibility="{Binding DataContext.IsInEdit, 
                                                     RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, 
                                                     Converter={StaticResource boolToVisibilityInverseConverter}}" 
                                Click="EditSaveButton_Click" 
                                Command="{Binding DataContext.EditCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"/>
                        <Button x:Name="btnSave" Grid.Row="1" Style="{StaticResource ResourceKey=SaveButton}" Height="35" Width="35" 
                                Visibility="{Binding DataContext.IsInEdit, 
                                                     RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, 
                                                     Converter={StaticResource boolToVisibilityConverter}}" 
                                Click="EditSaveButton_Click"
                                Command="{Binding DataContext.SaveCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"/>
                    </Grid>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Delete" Width="70" IsReadOnly="True">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="Auto" />
                        </Grid.RowDefinitions>
                        <Button x:Name="btnDelete" Style="{StaticResource ResourceKey=DeleteButton}" Height="35" Width="35"
                                Visibility="{Binding DataContext.IsInEdit, 
                                                     RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, 
                                                     Converter={StaticResource boolToVisibilityInverseConverter}}" 
                                Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"/>
                        <Button x:Name="btnCancel" Grid.Row="1" Style="{StaticResource ResourceKey=CancelButton}" Height="35" Width="35" 
                                Visibility="{Binding DataContext.IsInEdit, 
                                                     RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, 
                                                     Converter={StaticResource boolToVisibilityConverter}}" 
                                Command="{Binding DataContext.CancelCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"/>
                    </Grid>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>
<TextBox Grid.Column="0" Text="{Binding SearchGroupName, UpdateSourceTrigger=PropertyChanged}" />

在代码隐藏中:

private void CollectionViewSource_Filter(object sender, FilterEventArgs e)
{
    var a = e.Item.GetType().GetProperty("GroupName");
    if (a != null)
    {
        if (_viewModel.SearchGroupName != "")
        {
            var s = a.GetValue(e.Item, null);
            if (s != null)
                e.Accepted = s.ToString().Contains(_viewModel.SearchGroupName, StringComparison.OrdinalIgnoreCase);
            else
                e.Accepted = false;
        }
        else
            e.Accepted = true;
    }
}

在视图中模型:

ERPLiteDBContext db = new ERPLiteDBContext();
public ListViewModel()
{
    Groups = new ObservableCollection<Group>(db.Groups);
    SearchGroupName = "";
}
private string _searchGroupName;
public string SearchGroupName
{
    get
    {
        return _searchGroupName;
    }
    set
    {
        _searchGroupName = value;
        OnPropertyChanged("SearchGroupName");
    }
}
private ObservableCollection<Group> _groups;
public ObservableCollection<Group> Groups
{
    get
    {
        return _groups;
    }
    set
    {
        _groups = value;
        OnPropertyChanged("Groups");
    }
}

上面的代码有效。但是要使上面的代码正常工作,我必须在文本框中键入一些内容,然后单击 DataGrid 的标题对其进行排序。因此,简而言之,上面的代码不提供实时过滤。我想在文本框中键入内容时过滤数据......

使用文本框在数据网格中进行实时筛选

因此,代码中的过滤实际上是排序的后续。为了随时执行过滤,我建议对视图模型进行以下小的更改:

Group知道是否应该过滤。它具有IsHidden属性:

public class Group // actually a viewmodel
{
    public bool IsHidden
    {
        get;
        set;
    }
    public string Name
    {
        get;
        set;
    }
...
}

每次文本更改时,都会为集合中的每个成员设置IsHiddenCollectionViewSource检查此属性:

private void OnTextBoxTextChanged(object sender, TextChangedEventArgs e)
{
    // reset first to keep continious filtering
    Groups.ToList().ForEach(i => i.IsHidden = false);
    foreach (var filteredGroup in Groups.Where(vm => vm.Name == _viewModel.SearchGroupName))
    {
        filteredGroup.IsHidden = true;
    }
    ICollectionView cv = CollectionViewSource.GetDefaultView(_dataGrid.ItemsSource);
    if (cv != null)
    {
        // filter the Groups collection
        cv.Filter = (vm as Group) => vm.IsHidden == false;
    }
}