This is my code:
public partial class MyGS: ContentPage {
public MyGS() {
InitializeComponent();
BindingContext = new MyGSViewModel();
}
public class MyGSViewModel: INotifyCollectionChanged {
public event NotifyCollectionChangedEventHandler CollectionChanged;
public ObservableCollection < SchItem > Items {get;private set;}
public MyGSViewModel() {
Items = new ObservableCollection<SchItem>();
//Item Population
public void removeItem(int rid, int lid) {
SchItem myItem = Items[lid];
Items.Remove(myItem);
CollectionChanged ? .Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, myItem));
}
}
public class SchItem {
public int realm_id {get;set;}
public int list_id {get;set;}
public ICommand TapCommand {
get {return new Command(() => {
Debug.WriteLine("COMMAND: " + list_id);
MyGSViewModel gsvm = new MyGSViewModel();
gsvm.removeItem(realm_id, list_id);
});
}
}
}
}
When removeItem method is called the view doesn't refresh and the item will be no deleted from ListView, maybe the problem is about the CollectionChanged but i don't get how to fix that.
Note: Debugging in Android Device
A couple of things. Usually System.ComponentModel.INotifyPropertyChanged
is used instead of INotifyCollectionChanged
. If you switch to that and also implement a more common binding pattern, your ViewModel would look like this:
public class MyGSViewModel: INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection < SchItem > Items {
get { return _items; }
private set {
if(_items != value) {
_items = value;
OnPropertyChanged(); //Execute the event anytime an object is removed or added
}
}
}
public MyGSViewModel() {
Items = new ObservableCollection<SchItem>();
//Item Population
}
public void removeItem(int rid, int lid) {
SchItem myItem = Items[lid];
Items.Remove(myItem); //If an object is removed, the OnPropertyChanged() method will be run from 'Items's setter
}
protected virtual void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) {
PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
I would also suggest moving the OnPropertyChanged
method and the PropertyChanged
event into a base ViewModel so that all of your ViewModels can inherit from the base and you do not have duplicate that code everywhere.
*Edit: Just noticed that you have your TapCommand
defined within your SchItem
class. In there you are newing up a new MyGSViewModel
instance everytime that command is run. So unless everything in your MyGSViewModel
is set to static (which I do not recommend), that is not ever going to effect your MyGS
page. In addition to what I suggested above, I would suggest using the Tapped
event instead of a Command
since you need to pass multiple parameters into your removeItem
method.
To do that...
In your XAML:
<Button Tapped="OnItemTapped"/>
-OR-
<Label>
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="OnItemTapped"/>
</Label.GestureRecognizers>
</Label>
In your MyGS
ContentPage
:
public partial class MyGS : ContentPage {
private MyGSViewModel _viewModel;
public MyGS() {
InitializeComponent();
BindingContext = _viewModel = new MyGSViewModel();
}
private void OnItemTapped(object sender, EventArgs e) {
SchItem item = (SchItem)((Image)sender).BindingContext;
if(item == null) { return; }
_viewModel.removeItem(item.realm_id, item.list_id);
}
}