Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xamarin.Forms - ListView does not update when data changes

Problem: Data changes but ListView does not update

I have a ListView whose ItemsSource is set to

<ListView ItemsSource="{Binding ContactsGrouped}" 

On click of a button I update the query to only return records that contain the letters "Je". I can see that the right thing is being returned, and that ContactsGrouped is being updated, but the UI does not change.

public ObservableCollection<Grouping<string, Contact>> ContactsGrouped { get; set; }

where Grouping looks like this:

public class Grouping<K, T> : ObservableCollection<T>
{
    public K Key { get; private set; }

    public Grouping ( K key, IEnumerable<T> items )
    {
        Key = key;
        foreach ( var item in items )
            this.Items.Add( item );
    }
}

Given that I'm using ObservableCollections, I'd expect the list to redraw. Am I missing something obvious?

like image 650
Jesse Liberty Avatar asked Nov 25 '14 15:11

Jesse Liberty


2 Answers

I presume the Grouping class is utilised from a ViewModel. In which case that ViewModel has to implement the INotifyPropertyChanged interface such as below:

#region INotifyPropertyChanged implementation

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged ([CallerMemberName]string propertyName = null)
{
    if (PropertyChanged != null) {
        PropertyChanged (this, new PropertyChangedEventArgs (propertyName));
    }
}

#endregion

As long as you call the OnPropertyChnaged method on setting the property then you will get the results of the binding.

like image 163
JordanMazurke Avatar answered Oct 19 '22 01:10

JordanMazurke


Turns out that while implementing INotifyPropertyChanged still won't update the list when filtering it. However, factoring out the code that populates the list in the VM and then calling that code in the OnTextChanged method (followed by a call to resetting the ItemsSource) does the trick.

    public void OnTextChanged ( object sender, TextChangedEventArgs e ) {
        vm.PopulateContacts( vm.CurrentDataService );
        ContactListView.ItemsSource = vm.ContactsGrouped;
    }

The PopulateContacts method looks like this (abridged)...

    // setup
    // Get the data
        var sorted = 
            from contact in contacts
            orderby contact.FullName
            group contact by contact.FirstInitial 
            into contactGroup
            select new Grouping<string, Contact> ( contactGroup.Key, contactGroup );

        contactsGrouped = new ObservableCollection<Grouping<string, Contact>> ( sorted );

That works, and is reasonably clean and testable

like image 22
Jesse Liberty Avatar answered Oct 19 '22 01:10

Jesse Liberty