简体   繁体   English

在 WPF 中过滤 DataGrid

[英]Filter a DataGrid in WPF

I load a lists of objects in a datagrid with this:我用这个加载数据网格中的对象列表:

dataGrid1.Items.Add(model);

The model become data from a database. model成为数据库中的数据。 It has a Id(int) , Name(string) and Text(string)它有一个Id(int)Name(string)Text(string)

In my datagrid I show only the Name of the model .在我的数据网格中,我只显示model的名称。 How can I filter the datagrid now, when I enter something in a textbox?当我在文本框中输入内容时,现在如何过滤数据网格?

I was at this page: http://msdn.microsoft.com/en-us/library/vstudio/ff407126(v=vs.100).aspx but 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但我不明白那里的代码,我无法解释如何我应该为我的问题转换它。

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
    }

This is a simple implementation of using the Filter property of ICollectionView.这是使用 ICollectionView 的 Filter 属性的简单实现。 Suppose your XAML contains this:假设您的 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

@WiiMaxx, can't comment as not enough rep. @WiiMaxx,不能评论因为没有足够的代表。 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.一方面,它们可能会很慢,另一方面,如果将相同的过滤器应用于保存不同复杂类型数据的网格,则会出现 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”运算符不会像直接转换操作那样执行任何显式类型强制,因此过滤器将更快。

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

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

I found a dumb method and know this is an old question but ... Just use the Filter function on items property on the DataGrid object.我发现了一个愚蠢的方法,并且知道这是一个老问题,但是......只需在 DataGrid 对象上的 items 属性上使用 Filter 函数。 Like this: (I'm sorry but i learned only VB)像这样:(对不起,我只学了VB)

Public Property SearchName As String
    Get
        Return _SearchName
    End Get
    Set
        _SearchName = Value
        DG_drw_overview.Items.Filter = New Predicate(Of Object)(Function(x) x.Name.Contains(Value))           
    End Set
End Property

This property is changed every time you type something in the textbox.每次在文本框中键入内容时,此属性都会更改。 DG_drw_overview is the DataGrid instance. DG_drw_overview 是 DataGrid 实例。 In Predicate the object represents the object you put in the DataGrid.在 Predicate 中,对象代表您放入 DataGrid 中的对象。

Then bind the SearchName to textbox然后将 SearchName 绑定到文本框

<TextBox x:Name="TB_search" 
         Text="{Binding SearchName, UpdateSourceTrigger=PropertyChanged}"/>

Set datacontext of the textbox to the main class (usually after InitializeComponent())将文本框的datacontext设置为主类(通常在InitializeComponent()之后)

TB_search.DataContext = Me

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM