none
ObservableCollection Filter

    Question

  • Hi,

    Im new to working with data in this kind of way and have tied myself in knots trying to figure out how to filter an observable collection that is displayed in a listview.

    I have a class that defines the data and another class that houses the ViewModel.

    Public Class TasksViewModel
        Implements INotifyPropertyChanged
        Sub New()
    
        End Sub
    
        Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
        Private Sub NotifyPropertyChanged(ByVal propName As String)
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propName))
        End Sub
    
        Private _TaskList As ObservableCollection(Of Task)
        Public Property TaskList() As ObservableCollection(Of Task)
            Get
                Return _TaskList
            End Get
            Set(ByVal value As ObservableCollection(Of Task))
                _TaskList = value
                NotifyPropertyChanged("TaskList")
            End Set
        End Property
    End Class

    I bind my ListView to the TaskList that is described in the above class and it all works great.

    Also (and I don't know if this makes any difference) I populate the TaskList from a saved data file.

    what I would like to do is to filter the list depending on the state of one of the properties (for example, is something complete?)

    I have looked a examples but cannot get it to work and more importantly don't understand the thinking behind them.

    Could someone please point me in the right direction?

    Thanks

    Gimbal





    Thursday, October 24, 2013 4:19 PM

Answers

  • Using two collections is a good approach.  In your view model you would have something like this:

    private ObservableCollection<ItemViewModel> _filteredData;
    
    public ObservableCollection<ItemViewModel> FilteredData
    {
           get { return _filteredData; }
           set { _filteredData = value; RaisePropertyChanged("FilteredData"); }
    }
    
    public  void RefreshFilteredData()
    {
        //  Verify the Main Collection is valid, if not return
        //  Filter data
        var fc = from fcobjects in MainCollection
                       where "some filter"
                       select fcobjects;
        FilteredData = new ObservableCollection<ItemViewModel>(fc);
    }
    What are the specific errors you are getting? 


    Bret Bentzinger (MSFT) @awehellyeah

    Tuesday, October 29, 2013 4:09 PM
  • One case is to make a source observable collection and filtered collection and on each update make a new collection which you can pass into your model. But if you want to avoid problems with graphics effects like redrawing when you are using add/remove item effect in your list view (like default) you must do it otherwise.

    Make a source observable collection and on a change check if the item match the filter (in the case of yes-add it in a second observable collection). In case you would change the filter you should determinate what changes and compare with previous version. But you must also handle when an item changes so you must check if the item match the filter after update. 

    Tuesday, October 29, 2013 7:42 PM

All replies

  • Which example have you looked at and is confusing you?

    Jeff Sanders (MSFT)

    @jsandersrocks - Windows Store Developer Solutions @WSDevSol
    Getting Started With Windows Azure Mobile Services development? Click here
    Getting Started With Windows Phone or Store app development? Click here
    My Team Blog: Windows Store & Phone Developer Solutions
    My Blog: Http Client Protocol Issues (and other fun stuff I support)

    Friday, October 25, 2013 12:11 PM
  • I've looked at loads of different ones but cant seem to find one that seems to work for windows store apps.

    I've been trying to get it working by having 2 collections.

    The first is the original one that contains the whole collection and the second to contain the filtered version.
    The listview is bound to the filtered collection and when I check a check box, it clears the filtered list and iterates through the main collection and if a property is true then it gets added to the filtered view.

    I thought that this might work but I get errors.
    If I clear the filtered collection before I iterate and add, I get null errors and if I don't I get told that the enumeration operation may not execute.

    Am I making any kind of sense? Its kinda hard to explain.

    Thanks for taking the time to reply. I'm really struggling with this. I get the impression that it shouldn't be this hard but I cant seem to wrap my head around it.

    Sunday, October 27, 2013 1:31 PM
  • I've almost got it working using the method I mentioned above.
    I have 2 instances of the view model, one for the collection and one for the filtered collection.

    I've gotten around the issues I mentioned earlier but it seems if I clear the filtered collection the original one clears as well.

    I'm not quite sure why as the 2 collections are completely separate.

    Any ideas? or am I going about this completely the wrong way?

    Thanks

    Sunday, October 27, 2013 7:13 PM
  • Using two collections is a good approach.  In your view model you would have something like this:

    private ObservableCollection<ItemViewModel> _filteredData;
    
    public ObservableCollection<ItemViewModel> FilteredData
    {
           get { return _filteredData; }
           set { _filteredData = value; RaisePropertyChanged("FilteredData"); }
    }
    
    public  void RefreshFilteredData()
    {
        //  Verify the Main Collection is valid, if not return
        //  Filter data
        var fc = from fcobjects in MainCollection
                       where "some filter"
                       select fcobjects;
        FilteredData = new ObservableCollection<ItemViewModel>(fc);
    }
    What are the specific errors you are getting? 


    Bret Bentzinger (MSFT) @awehellyeah

    Tuesday, October 29, 2013 4:09 PM
  • One case is to make a source observable collection and filtered collection and on each update make a new collection which you can pass into your model. But if you want to avoid problems with graphics effects like redrawing when you are using add/remove item effect in your list view (like default) you must do it otherwise.

    Make a source observable collection and on a change check if the item match the filter (in the case of yes-add it in a second observable collection). In case you would change the filter you should determinate what changes and compare with previous version. But you must also handle when an item changes so you must check if the item match the filter after update. 

    Tuesday, October 29, 2013 7:42 PM