Filter a DataGrid in WPF

后端 未结 5 1987
庸人自扰
庸人自扰 2020-12-05 08:21

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

dataGrid1.Items.Add(model);

The model become data from a database. It has a

相关标签:
5条回答
  • 2020-12-05 08:50

    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):

        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):

        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

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

        // your Filter
        var yourComplexFilter= new Predicate<object>(ComplexFilter);
    
        private bool ComplexFilter(object obj)
        {
            //your logic
        }
    
    0 讨论(0)
  • 2020-12-05 08:51

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

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

    or

    dataGrid1.ItemsSource = this._myCollectionOfModels;
    

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

    0 讨论(0)
  • 2020-12-05 08:53

    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.

    0 讨论(0)
  • 2020-12-05 09:01

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

    <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.

    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

    0 讨论(0)
  • 2020-12-05 09:01

    @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.

    // 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.

    0 讨论(0)
提交回复
热议问题