0

I have custom control that takes a list of object and present them in sort of listview.

public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(nameof(ItemsSource), typeof(IEnumerable<object>), typeof(MyCustomControl), null);
    public IEnumerable<object> ItemsSource
    {
        get { return (IEnumerable<object>)GetValue(ItemsSourceProperty); }
        set{ SetValue(ItemsSourceProperty, value);}
    }

From the ViewModel I would be binding the ItemsSource to an ObservableCollection<object> and I would like my custom control to listen to the collectionchanged event on the ObservableCollection rather than propertychanged.

ListView some how able to listen to the collection changed and refreshes its view, I tried to find the code from the Xamarin github, no luck in finding where the listener is binded.

Any solution, how I can listen to the collection from my custom control?

Luminous_Dev
  • 614
  • 6
  • 14

2 Answers2

0

You can add an event to your collection using ObservableCollection<T>.CollectionChanged. more info here. And you can handle changes in you view using a callback mechanism like below

In your ViewModel something like this

public ObservableCollection<Item> myObservableList { get; set; }
MyChangeHandler handler;

//Pass a callback to your viewModel to listen to changes in your view
public YourViewModel(MyChangeHandler handler)
{
   this.myObservableList = new ObservableCollection<Item>();
   this.myObservableList.CollectionChanged += this.OnCollectionChanged;
}

//Handle collection changes
void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
//...Call your custom control method here
    handler.someMethod("List changed");
}

public interface MyChangeHandler{
    void someMethod(string value);
}

And in your custom view

class MyView: ContentView,MyChangeHandler{
    public MyView(){
        var vm = new YourViewModel(this);
    } 

    public someMethod(string value){
        ///Handle changes in your view
    }
}
Fahadsk
  • 1,099
  • 10
  • 24
  • How about a way to implement collctionchanged event inside the CustomControl rather than invoking from viewmodel? – Luminous_Dev Feb 27 '18 at 09:27
  • It depends on your application design. You can write all code in a single class or (View) or separate in some manageable modules, following a pattern would save your time in long run. – Fahadsk Feb 27 '18 at 09:45
0

Okay Answering my own post

I was suggested by many other people to use MessagingCenter, Collection event in the ViewModel, create custom eventhandler inside the Custom control...These are all work around, not solution.

If its bug then work around would be best solution but since the way how bindableproperty is implemented, we are able to achieve this using the actual provided design.

So in custom control

protected override void OnPropertyChanged(string propertyName)
{
    if(propertyName == CustomView.ItemsSourceProperty.PropertyName)
    {
        if (ItemsSource != null && ItemsSource is INotifyCollectionChanged collection)
        {
                collection.CollectionChanged -= ItemsSourceCollectionChanged;
                collection.CollectionChanged += ItemsSourceCollectionChanged;
        }

    }

    base.OnPropertyChanged(propertyName);
}

private void ItemsSourceCollectionChanged(object s, EventArgs e)
{
    //Handle collection changed event
}

When ItemsSource property is changed, it resubscribe to collectionchanged event.

Luminous_Dev
  • 614
  • 6
  • 14