ScarletMerlin
ScarletMerlin

Reputation: 475

ObservableCollection.CollectionChanged not being called

Ok, I have search and nothing I see gives me a solution so here I go. I have a public ObservableCollection<Photo> Items { get; set;} that doesn't update the UI in MonoDroid everything on Monotouch works fine.

Upon further review: Remove and Add both aren't not refreshing the collection. I have to rotate the device to see the changes. (only on Android)

my view is bound like this:

this.BindingContext = _viewModel;

        var activityIndicator = new BrandActivityIndicator{
            VerticalOptions = LayoutOptions.Start,
            HorizontalOptions = LayoutOptions.Center
        };

        activityIndicator.SetBinding<PhotosViewModel>(BrandActivityIndicator.IsVisibleProperty, vm => vm.IsBusy);
        activityIndicator.SetBinding<PhotosViewModel>(BrandActivityIndicator.IsRunningProperty, vm => vm.IsBusy);

        this.Padding = new Thickness(10, 5, 10, 0);
        this.HorizontalOptions = LayoutOptions.FillAndExpand;
        this.VerticalOptions = LayoutOptions.FillAndExpand;

        _gridView = new GridView
        {      
            RowSpacing = 15,
            ColumnSpacing = 15,        
            ItemWidth = 85,        
            ItemHeight = 85,       
            HorizontalOptions = LayoutOptions.FillAndExpand,       
            VerticalOptions = LayoutOptions.FillAndExpand,     
            ItemTemplate = new DataTemplate(typeof(ImagesViewCell))
        };     

        _gridView.SetBinding<PhotosViewModel> (GridView.ItemsSourceProperty, vm => vm.Items); 
        _gridView.SetBinding<PhotosViewModel> (GridView.IsVisibleProperty, vm => vm.NotBusy);        

        var layout = new StackLayout
            {
                VerticalOptions = LayoutOptions.FillAndExpand,
                Children = {
                    activityIndicator,
                    _gridView
                }
            };

        this.Content = layout;

GridView is but a ContentView

public class GridView : ContentView
{
    public GridView()
    {
        SelectionEnabled = true;

    }

    public static readonly BindableProperty ItemsSourceProperty = 
        BindableProperty.Create<GridView,IEnumerable>(p => p.ItemsSource, null);
}

the viewModel is standard

public class PhotosViewModel : BaseViewModel, IBadge
    {
        private readonly TaskScheduler _scheduler = TaskScheduler.FromCurrentSynchronizationContext();

        public ObservableCollection<Photo> Items { get; set;}
        public PhotosViewModel()
        {
            Items = new ObservableCollection<Photo>();

        }
}

I tried attaching a Items.CollectionChanged += notify and it wasn't called. At this moment I am out ideas.

Upvotes: 2

Views: 2283

Answers (2)

ScarletMerlin
ScarletMerlin

Reputation: 475

I found the answer, I created a custom renderer and bound the property using InotifyCollectionChanged.

if (newElement != null)
            {
                newElement.PropertyChanging += ElementPropertyChanging;
                newElement.PropertyChanged += ElementPropertyChanged;
                if (newElement.ItemsSource is INotifyCollectionChanged)
                    (newElement.ItemsSource as INotifyCollectionChanged).CollectionChanged += DataCollectionChanged;
            }


protected virtual void ElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "ItemsSource")
            {
                if (Element.ItemsSource is INotifyCollectionChanged)
                    (Element.ItemsSource as INotifyCollectionChanged).CollectionChanged += DataCollectionChanged;

                context.RunOnUiThread (() => UpdateFromCollectionChange ());
            }
        }

for whatever reason out there the ObservableCollection doesn't fire the collectionChanged event on Android using Xamarin.forms without a renderer.

Upvotes: 0

Dean Chalk
Dean Chalk

Reputation: 20461

This is a bit of a guess, bit it may be possible that there is a bug in the Android implementation of ContentView. You are trying to bind your ObsevableCollection to a binding that is declared as IEnumerable. This shouldn't matter, but maybe there is a bug where the android implementation detects IEnumerable but doesn't test its underlying type to see if it is also INotifyCollectionChanged. Try changing it from IEnumerable to the concrete type and see if that works. As I said, this is a guess based on similar issues I found in the WPF world.

Upvotes: 1

Related Questions