C# 在 WPF 中过滤 DataGrid

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15568325/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 17:12:16  来源:igfitidea点击:

Filter a DataGrid in WPF

c#wpfdatagridfilter

提问by Karl_Schuhmann

I load a lists of objects in a datagrid with this:

我用这个加载数据网格中的对象列表:

dataGrid1.Items.Add(model);

The modelbecome data from a database. It has a Id(int), Name(string)and Text(string)

model成为数据库中的数据。它有一个Id(int),Name(string)Text(string)

In my datagrid I show only the Name of the model. How can I filter the datagrid now, when I enter something in a textbox?

在我的数据网格中,我只显示model. 当我在文本框中输入内容时,现在如何过滤数据网格?

I was at this page: http://msdn.microsoft.com/en-us/library/vstudio/ff407126(v=vs.100).aspxbut I don't understand the code from there and I can not explain how I should transpose that for my problem.

我在这个页面上:http: //msdn.microsoft.com/en-us/library/vstudio/ff407126(v=vs.100).aspx但我不明白那里的代码,我无法解释如何我应该为我的问题转换它。

采纳答案by WiiMaxx

there are multiple way's to filter Collection

有多种过滤集合的方法

let's suggesting this is your Item Class

让我们建议这是您的项目类

public class Model
{
    public string Name
    {
        get;
        set;
    }
}

and your collection looks like

你的收藏看起来像

       var ObColl = new ObservableCollection<Model>();

        ObColl.Add(new Model() { Name = "John" });
        ObColl.Add(new Model() { Name = "Karl" });
        ObColl.Add(new Model() { Name = "Max" });
        ObColl.Add(new Model() { Name = "Mary" });

Way 1 (Predicate):

方式1(谓词):

    public MainWindow()
    {
        InitializeComponent();

        // Collection which will take your ObservableCollection
        var _itemSourceList = new CollectionViewSource() { Source = ObColl };

        // ICollectionView the View/UI part 
        ICollectionView Itemlist = _itemSourceList.View;

        // your Filter
        var yourCostumFilter= new Predicate<object>(item => ((Model)item).Name.Contains("Max"));

        //now we add our Filter
        Itemlist.Filter = yourCostumFilter;

        dataGrid1.ItemsSource = Itemlist;
    }

Way 2 (FilterEventHandler):

方式二(FilterEventHandler):

    public MainWindow()
    {
        InitializeComponent();

        // Collection which will take your Filter
        var _itemSourceList = new CollectionViewSource() { Source = ObColl };

       //now we add our Filter
       _itemSourceList.Filter += new FilterEventHandler(yourFilter);

        // ICollectionView the View/UI part 
        ICollectionView Itemlist = _itemSourceList.View;

        dataGrid1.ItemsSource = Itemlist;
    }

    private void yourFilter(object sender, FilterEventArgs e)
    {
        var obj = e.Item as Model;
        if (obj != null)
        {
            if (obj.Name.Contains("Max"))
                e.Accepted = true;
            else
                e.Accepted = false;
        }
    }

extended Information to Way 1

将信息扩展到方式 1

if need multiple conditions or some complex Filter you can add a method to your Predicat

如果需要多个条件或一些复杂的过滤器,您可以向您的 Predicat 添加一个方法

    // your Filter
    var yourComplexFilter= new Predicate<object>(ComplexFilter);

    private bool ComplexFilter(object obj)
    {
        //your logic
    }

回答by blindmeis

take at look at DataBinding --> in your case dont add items to your grid, but set the itemssource

看看 DataBinding --> 在您的情况下,不要将项目添加到您的网格,而是设置项目源

<Datagrid ItemsSource="{Binding MyCollectionOfModels}" />

or

或者

dataGrid1.ItemsSource = this._myCollectionOfModels;

and if you want some kind of filtering,sorting, grouping look at CollectionView

如果您想要某种过滤、排序、分组,请查看CollectionView

回答by Loránd Biró

This is a simple implementation of using the Filter property of ICollectionView. Suppose your XAML contains this:

这是使用 ICollectionView 的 Filter 属性的简单实现。假设您的 XAML 包含以下内容:

<TextBox x:Name="SearchTextBox" />
<Button x:Name="SearchButton"
        Content="Search"
        Click="SearchButton_OnClick"
        Grid.Row="1" />
<DataGrid x:Name="MyDataGrid"
          Grid.Row="2">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Lorem ipsum column"
                            Binding="{Binding}" />
    </DataGrid.Columns>
</DataGrid>

Then in the constructor you can get the default view for your data where you can set the filter predicate which will be executed for every item of your collection. The CollectionView won't know when it should update the collection, so you have to call Refresh when the user clicks the search button.

然后在构造函数中,您可以获得数据的默认视图,您可以在其中设置过滤谓词,该谓词将为您的集合的每个项目执行。CollectionView 不知道它何时应该更新集合,因此当用户单击搜索按钮时您必须调用 Refresh。

private ICollectionView defaultView;

public MainWindow()
{
    InitializeComponent();

    string[] items = new string[]
    {
        "Asdf",
        "qwer",
        "sdfg",
        "wert",
    };

    this.defaultView = CollectionViewSource.GetDefaultView(items);
    this.defaultView.Filter =
        w => ((string)w).Contains(SearchTextBox.Text);

    MyDataGrid.ItemsSource = this.defaultView;
}

private void SearchButton_OnClick(object sender, RoutedEventArgs e)
{
    this.defaultView.Refresh();
}

At this url you can find a more detailed description of CollectionViews: http://wpftutorial.net/DataViews.html

在这个 url 你可以找到更详细的 CollectionViews 描述:http: //wpftutorial.net/DataViews.html

回答by steve

@WiiMaxx, can't comment as not enough rep. I would be a bit more careful about the direct casts there. They can be slow for one thing and for another, if the same filter was applied to a grid holding different complex type data you would have an InvalidCastException.

@WiiMaxx,不能评论因为没有足够的代表。我会对那里的直接演员更加小心。一方面,它们可能会很慢,另一方面,如果将相同的过滤器应用于保存不同复杂类型数据的网格,则会出现 InvalidCastException。

// your Filter
    var yourCostumFilter= new Predicate<object>(item =>
    {
        item = item as Model;
        return item == null || item.Name.Contains("Max");
    });

This will not break you datagrid and will not filter the results if the cast fails. Less impact to your users if you get the code wrong. On top of that the filter will be faster due to the "as" operator not doing any explicit type coercion as the direct cast operation will.

如果转换失败,这不会破坏您的数据网格并且不会过滤结果。如果您弄错了代码,对您的用户的影响就会减少。最重要的是,由于“as”运算符不会像直接转换操作那样执行任何显式类型强制,因此过滤器将更快。

回答by Joee

You can use dataview filter in order to filter the datagrid rows.

您可以使用数据视图过滤器来过滤数据网格行。

            DataView dv = datatable.DefaultView;

            StringBuilder sb = new StringBuilder();
            foreach (DataColumn column in dv.Table.Columns)
            {
                sb.AppendFormat("[{0}] Like '%{1}%' OR ", column.ColumnName, "FilterString");
            }
            sb.Remove(sb.Length - 3, 3);
            dv.RowFilter = sb.ToString();
            dgvReports.ItemsSource = dv;
            dgvReports.Items.Refresh();

Where the "datatable" is datasource given to your datagrid and using string builder you build the filter query where "Filter String" is the text you want to search in your datagrid and set it to dataview and finally set the dataview as itemsource to your datagrid and refresh it.

其中“数据表”是提供给数据网格的数据源,并使用字符串构建器构建过滤器查询,其中“过滤字符串”是要在数据网格中搜索的文本并将其设置为数据视图,最后将数据视图设置为数据网格的项目源并刷新它。