简体   繁体   中英

Applying where on ObservableCollection doesn't reflect on datagrid

I try to "filter" an ObservableCollection and update the bound DataGrid.

 ObservableCollection<Record> recordObservableCollection;
recordObservableCollection = new ObservableCollection<Record>(GetData()); //GetData() returns  IEnumerable<Record>

dataGrid1.ItemsSource = recordObservableCollection;

Then I try to filter this collection:

 recordObservableCollection = new ObservableCollection<Record>(recordObservableCollection.Where(filter));//filter is Func<Data.Record, bool>

recordObservableCollection is updated fine.

But the DataGrid is not updated.

Your field or variable called recordObservableCollection has one value initially and a different value after filtering. Because you used new ObservableCollection<Record>(...) twice you created two separate observable collection instances.

The problem is that the DataGrid is still referring to the first instance . Even though you have changed recordObservableCollection , that only affects its value. The value of DataGrid.ItemsSource is still what it was before the filtering .

To fix this problem, you need to re-assign the new collection's value to the ItemSource property. Simply repeat what you did the first time, but after the filtering:

dataGrid1.ItemsSource = recordObservableCollection;

and now ItemSource will be set to the new value of recordObservableCollection .

Expose the ObservableCollection<Record> as a public property

also

Using ObservableCollection only affect binding when you add/remove items from your list. By using ObservableCollection you do not need to reset binding to the list or DataGrid when your collection changed (not the item inside collection changed). But they do not have any effect when your data object properties changed. For that you need to implement INotifyPropertyChanged interface for your DataObject.

ObservableCollection will get update because ObservableCollection (System.Collections.ObjectModel) throws an event every time the collection get changed but you have to set the filter collection as itemsource again other wise it wont update the UI...

The best way to do this use a public property that you'll bind in control as item source and in that property you will define NotifyPropertyChanged in setter . Every time you'll change the collection using this property the control will also be updated ...

Let Suppose you have your data grid in test.xaml

--> First fo all work for INotifyPropertyChanged add an abstract class in your project inherit it from INotifyPropertyChanged interface and define OnPropertyChanged method

 public abstract class ViewModelBase : INotifyPropertyChanged
 {
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

}

--> After add a class in your project named it testViewModel which will inherit your ViewModelBase Class..

--> Now in testViewModel you'll make a property for your grid binding like this

  Private ObservableCollection<Record> _recordObservableCollection
  public  ObservableCollection<Record> recordObservableCollection
  {
  get
  {
       if(_recordObservableCollection == null)
        {
         _recordObservableCollection = new ObservableCollection<Record>(GetData());
         recordObservableCollection = new ObservableCollection<Record>(recordObservableCollection.Where(filter));
        }
       return _recordObservableCollection;
  }
 Set
  {

     _recordObservableCollection = Value;
      OnPropertyChanged("recordObservableCollection"); //Your property name 
  }

}

here now if u update your collection using property on any other property, method or command UI will be updated beacsue in setter you have defined OnPropertyChanged...

Now comes back to test.xaml here you have to do two things

  1. Set dataContext of test.xaml either in code behing or in in xaml (In Code behind just after InitializeComponent() make an intance of viewmodel class and assign it as DataContext like this

      public test() { InitializeComponent(); testViewModel vm = new testViewModel(); this.DataContext = vm; } 
  2. Bind property you defined in testViewModel to grid

      <Grid Name="MyGrid" DataContext="{Binding recordObservableCollection}"> </Grid> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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