在WPF中筛选DataGrid

时间:2013-03-22 10:41:43

标签: c# wpf datagrid filter

我在数据网格中加载一个对象列表:

dataGrid1.Items.Add(model);

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

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

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

6 个答案:

答案 0 :(得分:32)

有多种方法来过滤收藏

让我们建议这是你的物品类

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

,您的收藏品看起来像

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

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

方式2(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;
        }
    }

将信息扩展到方式1

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

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

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

答案 1 :(得分:5)

这是使用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>

然后在构造函数中,您可以获取数据的默认视图,您可以在其中设置将为集合的每个项目执行的过滤谓词。 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();
}

在此网址中,您可以找到有关CollectionViews的更详细说明: http://wpftutorial.net/DataViews.html

答案 2 :(得分:3)

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

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

这不会破坏您的数据网格,并且如果转换失败则不会过滤结果。如果代码错误,对用户的影响较小。最重要的是,由于“as”操作符没有像直接强制转换操作那样进行任何显式类型强制,过滤器会更快。

答案 3 :(得分:0)

看一下DataBinding - &gt;在你的情况下,不要将项添加到你的网格,但设置itemssource

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

dataGrid1.ItemsSource = this._myCollectionOfModels;

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

答案 4 :(得分:0)

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

            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();

&#34;数据表&#34;是给数据网格的数据源,并使用字符串构建器构建过滤器查询,其中&#34; Filter String&#34;是您要在数据网格中搜索的文本,并将其设置为dataview,最后将dataview设置为itemsource到datagrid并刷新它。

答案 5 :(得分:0)

我发现了一个愚蠢的方法,并且知道这是一个老问题,但是...只需在 DataGrid 对象的 items 属性上使用 Filter 函数即可。像这样:(对不起,我只学了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

每次您在文本框中键入内容时,此属性都会更改。 DG_drw_overview 是 DataGrid 实例。在 Predicate 中,对象代表您放入 DataGrid 中的对象。

然后将 SearchName 绑定到文本框

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

设置textbox的datacontext为主类(一般在InitializeComponent()之后)

TB_search.DataContext = Me