使用TextBox在DataGrid中实时过滤

时间:2014-11-27 10:48:37

标签: c# wpf datagrid

我有一个文本框和一个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}" />

在CodeBehind中:

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

在ViewModel中:

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

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

1 个答案:

答案 0 :(得分:1)

因此,代码中的过滤实际上是排序的后续操作。要随时执行过滤,我建议您关注,对视图模型进行少量更改:

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

public class Group // actually a viewmodel
{
    public bool IsHidden
    {
        get;
        set;
    }
    public string Name
    {
        get;
        set;
    }
...
}
每次Text更改时,都会为集合中的每个成员设置

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