0

I have added the class

public class ObservableCollectionEx<T> : ObservableCollection<T>
{
    public bool SuppressEvents { get; set; } = true;

    public ObservableCollectionEx(): base() {}
    public ObservableCollectionEx(IEnumerable<T> collection): base(collection){}
    public ObservableCollectionEx(List<T> list): base(list){}

    public void RaiseCollectionChangedEvent()
    {
        SuppressEvents = false;

        this.OnPropertyChanged(new PropertyChangedEventArgs("Count"));
        this.OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
        this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
    }

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if (!SuppressEvents)
            base.OnCollectionChanged(e);
    }
}

ViewModel


public ObservableCollectionEx<MyModel> myCollection = new ObservableCollectionEx<MyModel>();

Method1()
{
   myCollection.SuppressEvents = true;
   //some changes in Obs Collection.
   // some add/remove/insert operations on collection
   myCollection.RaiseCollectionChangedEvent(); // works
}

Method2()
{
   myCollection.SuppressEvents = true;
   //some changes in Obs Collection.
   // some add/remove/insert operations on collection
   myCollection.RaiseCollectionChangedEvent(); // breaks
}

And in ViewModel, I'm suppressing the events by toggling the variable before the changes and after changes by calling the RaiseCollectionChangedEvent method. It is working in some scenarios. In some, it is throwing a null pointer exception. I'm not able to observe what causes the exception.

P.S. Error

Message Object reference not set to instance of an object

StackTrace Android: at Xamarin.Forms.Platform.Android.GridLayoutSpanSizeLookup.GetSpanSize (System.Int32 position) [0x00000] in D:\a\1\s\Xamarin.Forms.Platform.Android\CollectionView\GridLayoutSpanSizeLookup.cs:18 at AndroidX.RecyclerView.Widget.GridLayoutManager+SpanSizeLookup.n_GetSpanSize_I (System.IntPtr jnienv, System.IntPtr native__this, System.Int32 position) [0x00008] in D:\a\1\s\generated\androidx.recyclerview.recyclerview\obj\Release\monoandroid9.0\generated\src\AndroidX.RecyclerView.Widget.GridLayoutManager.cs:510

iOS: at Xamarin.Forms.Platform.iOS.ItemsViewController1[TItemsView].UpdateTemplatedCell (Xamarin.Forms.Platform.iOS.TemplatedCell cell, Foundation.NSIndexPath indexPath) [0x00031] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ItemsViewController.cs:278 at Xamarin.Forms.Platform.iOS.ItemsViewController1[TItemsView].CreateMeasurementCell (Foundation.NSIndexPath indexPath) [0x0007b] in D:\a\1\s\Xamarin.Forms.Platform.iOS\CollectionView\ItemsViewController.cs:619

Shubham Tyagi
  • 798
  • 6
  • 21
  • 2
    Where does the exception occur? How did you conclude it was this particular code that contains the problem? – Jeroen Mostert Apr 19 '22 at 08:20
  • Occurs just after this line `base.OnCollectionChanged(e);` , The exception is in native android/ios. Is there another cleaner way to do this? To stop and then start event of collection changed. because the non-stop event firing is wreaking havoc on the xamarin UI – Shubham Tyagi Apr 19 '22 at 08:36
  • 1
    It looks to me that the event triggers the view to update, and something within is `null` and causes an exception. I'd doubt suppressing event is the issue. You need to dig further - you should be able to inspect using the debugger. – Charles Mager Apr 19 '22 at 09:15
  • Suppressing change events is a gross hack to avoid a problem that is somewhere else in your code. You should instead find the real problem - I recommend "divide and conquer" - comment out all the xaml and code that is NOT part of UI for the collection. That will isolate whether it is something inside the collection, or something elsewhere on the page. Continue adding and removing code and xaml, until you find what is null. – ToolmakerSteve Apr 19 '22 at 16:19
  • @ToolmakerSteve There is no problem in my code, I just don't want unlimited event triggers while I'm making changes, and only want the changes to reflect once I'm done making them. This is just standard optimization that I'm unable to do. – Shubham Tyagi Apr 20 '22 at 08:33
  • Ok. When you say there is no problem in your code, does that mean that if you comment out `myCollection.SuppressEvents = true;`, then there is no null exception? DO still call `RaiseCollectionChangedEvent` at end - just comment out the one line. – ToolmakerSteve Apr 20 '22 at 16:37
  • If I don't use my Custom Observable Class `ObservableCollectionEx` there is no issue. I just want to know how to make this usable. – Shubham Tyagi Apr 20 '22 at 18:07
  • Hope the source code of ObservableCollection can give u some insights:https://github.com/microsoft/referencesource/blob/master/System/compmod/system/collections/objectmodel/observablecollection.cs – Alexandar May - MSFT Apr 21 '22 at 09:35

0 Answers0