Удалить элемент из списка на Tap
Это мой код:
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);
});
}
}
}
}
Когда вызывается метод removeItem, представление не обновляется, и элемент не будет удален из ListView, возможно, проблема в CollectionChanged, но я не понимаю, как это исправить.
Примечание. Отладка на устройстве Android
1 ответ
Пара вещей. Обычно System.ComponentModel.INotifyPropertyChanged
используется вместо INotifyCollectionChanged
, Если вы переключитесь на это и также реализуете более общий шаблон привязки, ваша ViewModel будет выглядеть так:
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));
}
}
Я бы также предложил переместить OnPropertyChanged
метод и PropertyChanged
событие в базовую ViewModel, так что все ваши ViewModel могут наследовать от базы, и у вас не будет дублировать этот код везде.
* Редактировать: только что заметил, что у вас есть TapCommand
определены в вашем SchItem
учебный класс. Там вы обновляете новый MyGSViewModel
экземпляр каждый раз, когда эта команда запускается. Так что, если все в вашем MyGSViewModel
установлен на статический (что я не рекомендую), это никогда не повлияет на ваш MyGS
стр. В дополнение к тому, что я предложил выше, я бы предложил использовать Tapped
событие вместо Command
так как вам нужно передать несколько параметров в ваш removeItem
метод.
Для этого...
В вашем XAML:
<Button Tapped="OnItemTapped"/>
-ИЛИ ЖЕ-
<Label>
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="OnItemTapped"/>
</Label.GestureRecognizers>
</Label>
В вашем 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);
}
}