Rock3rRullz
Rock3rRullz

Reputation: 465

CollectionViewSource doesn't update the UI

I am trying to implement a filtering and paging on a ListView. I managed to do the filtering but I observed that the UI doesn't get updated when I am adding/removing items from the collection.

Here is my setup: XAML:

   <ListView
           ItemsSource="{Binding SourceCollection, UpdateSourceTrigger=Explicit}"
           ScrollViewer.HorizontalScrollBarVisibility="Hidden"
           ScrollViewer.VerticalScrollBarVisibility="Auto"/>

VM Side:

  private CollectionViewSource _usersCollection;

CTOR

  _usersCollection = new CollectionViewSource {Source = UsersCollection};
  _usersCollection.Filter += usersCollection_Filter;

Props:

  public ICollectionView SourceCollection => _usersCollection.View;
  public List<User> UsersCollection => LiteDbHelper.GetAllUsers();

Then when I am adding a new item I tried to Refresh() the collection (both SourceCollection and _usersCollection) with no luck, also tried to RaisePropertyChanged on UsersCollection, again with no luck. The UI stays the same as the first time created.

P.S. I am adding records to a file-DB (LiteDB) and then I need to retrieve them from the DB and update the UI. This worked till I started to use the ICollectionView.

Any hints?

Update: I managed to fix this issue with the following code:

Changed the property that was feeding the CollectionViewSource:

 private ObservableCollection<User> _usersCollectionDB = new ObservableCollection<User>();
    public ObservableCollection<User> UsersCollection
    {
        get
        {
            if (_usersCollectionDB.Count == 0)
            {
                var allUsers = LiteDbHelper.GetAllUsers();
                _usersCollectionDB.AddRange(allUsers);
                return _usersCollectionDB;
            }

            return _usersCollectionDB;

        }
        set => _usersCollectionDB = value;
    }

and on the add method I just used these lines and it worked:

        var allUsers = LiteDbHelper.GetAllUsers();
        _usersCollectionDB.Clear();
        _usersCollectionDB.AddRange(allUsers);

        _usersCollection.View.Refresh();

Upvotes: 1

Views: 2999

Answers (1)

dymanoid
dymanoid

Reputation: 15197

Your source collection is a simple list:

List<User> UsersCollection => LiteDbHelper.GetAllUsers();
_usersCollection = new CollectionViewSource { Source = UsersCollection };

This is the reason you won't get any UI updates. The UsersCollection property will be queried by the CollectionViewSource one time, so the CollectionViewSource's instance will work only with that single list of items that were retrieved on initialization.

If you check out the documentation, you will see the following:

If the source collection implements the INotifyCollectionChanged interface, the changes raised by the CollectionChanged event are propagated to the views.

The source collection needs to implement INotifyCollectionChanged. That's e.g. an ObservableCollection<T>.

So the solution is: instead of using dynamically created lists, you should use an ObservableCollection<User> as a source for the CollectionViewSource.

ObservableCollection<User> usersObservableCollection = new ObservableCollection<User>();
_usersCollection = new CollectionViewSource { Source = usersObservableCollection };

Additionally, you will need to change your code so that this usersObservableCollection is populated by the items from your database.

Upvotes: 1

Related Questions