【问题标题】:Filter a DataGrid in WPF在 WPF 中过滤 DataGrid
【发布时间】:2013-03-12 04:34:25
【问题描述】:

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

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,但我不理解那里的代码,我无法解释我应该如何为我的问题转换它。

【问题讨论】:

  • 说出您的具体问题。你创建的代码是什么?我们可以告诉你有什么问题。
  • 我不明白,如何使用 CollectionViewSource 来解决我的问题。你能解释一下我如何在我的数据网格中使用“集合..”加载数据以及如何过滤它。 @Kylerrr

标签: c# wpf datagrid filter


【解决方案1】:

我发现了一个愚蠢的方法,并且知道这是一个老问题,但是......只需在 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}"/>

将文本框的datacontext设置为主类(一般在InitializeComponent()之后)

TB_search.DataContext = Me

【讨论】:

    【解决方案2】:

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

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

    dataGrid1.ItemsSource = this._myCollectionOfModels;
    

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

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        【解决方案4】:

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

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

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

        【讨论】:

        • 我测试了你的代码我无法编译它。你需要在你的逻辑中做var model = item as Model; 和我们model 然后它会正常工作
        【解决方案5】:

        有多种过滤收藏的方法

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

        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
            }
        

        【讨论】:

        • 你好,我也有类似的问题。你能看看这篇文章,告诉我这样做是否正确吗?这真的很有帮助。谢谢 :) -stackoverflow.com/questions/15569445/…
        • 我想根据当前的情况来看看哪种方法最合适的建议。愿意将其添加到您的答案中吗?如果你愿意的话,有一个很酷的 +1 等着你... :)
        • @KonradViltersten mhh 我会说这取决于您的喜好。如果您喜欢与我们合作的活动FilterEventHandler,如果您更喜欢对象,请使用Predicate 解决方案。我也不得不承认我对性能差异一无所知
        【解决方案6】:

        这是使用 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();
        }
        

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-11-10
          • 2013-06-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多