ObservableCollection / ObservableRangeCollection Set is never triggered

411 views Asked by At

I'm using lists in my program and I need the list to update without me having to set the item source to null every time I get new information.

The recommended workaround is to use an ObservableCollection, so that's what I did. Everything worked great! I called the ObservableCollection and it activated the "get {...};" and when I added or removed from the ObservableCollection it activated the "set {...};"

ObservableCollection<Class> list = new ObservableCollection<Class>();
public ObservableCollection<Class> List
{
     get => list;
     set 
     {
          {...}
     }
}

Originally I was using the standard new file version of Xamarin forms (5.0.0.2196) and Xamarin Essentials (1.7.0) to test my properties and bindings and everything worked fine.

Then I did I ruined everything by updating Xamarin forms and Xamarin Essentials to the latest versions :(

Ever since, my ObservableCollection never activates the "set {...};" code. Does anyone know how to trigger the "set" code or the On Collection Changed code?

And how should my new property constructors look?


[EDIT]

Thanks to the awesome responses, I got it all figured out!

To create a collection changed event, you just have to add the following code in your page constructor:

public PageVM 
{
     list.CollectionChanged += [Tab] or List_CollectionChanged
}

private void List_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    //This Method is generated automatically by pressing [Tab]
    {...}
}

When the entire collection is set to a value,

example//

ObservableCollection<string> list = new ObservableCollection<string> ();
ObservableCollection<string> List 
{
     get => list;
     set 
     {
         list = value;
         {...}
     }
}
ObservableCollection<string> List2 = new ObservableCollection<string> { "e", "f", "g" };
List = List2

the "set {...};" code is called and executed. However, when the collection is "changed" with .Add() or .Remove(), the Collection Changed Event is triggered.

example// 

List.Add("g"); 
or
List.Remove("a");

Great! Everything makes sense now; right? Well, not so fast... If you try to set the value of an ObservableCollection in a method and then later in that same method add or remove a value, it won't trigger a collection changed event. Instead of automatically executing the Collection Changed event, you will have to manually add an OnPropertyChanged(nameof(List)) in the method that changed the ObservableCollection to update the UI.

example//

public void MethodThatChangesObservableObject()
{
     List = List1;
     //Triggers "set {...};" from constructor
     
     List.Add("w");
     List.Remove("a");
     //Neither the add or remove will trigger a collection changed event

     OnPropertyChanged(nameof(List));
     //Will make Xamarin Forms aware that the UI need to be refreshed
}

If you add or remove an item from the ObservableCollection before "List = List2;" everything will be triggered as expected. However, any "changes" that are made to the ObservableCollection after the value is "set" in a given method won't trigger any other events.

Thanks again to everyone who contributed to helping me solve my question! This may be quite long but I hope this will help anyone who is currently learning Xamarin Forms like I am!

1

There are 1 answers

0
Michal Diviš On

You only need to create the ObservableCollection once. Adding/removing items will trigger the CollectionChanged event. You can subscribe to that event to react to changes like this:

using System.Collections.ObjectModel;

public class DemoViewModel
{
    public ObservableCollection<Book> Books { get; } = new ObservableCollection<Book>();

    public DemoViewModel()
    {
        Books.CollectionChanged += Books_CollectionChanged;
    }

    private void Books_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        //do something when items are added/removed
    }
}