点击时删除列表视图中的项目
Remove item in listview on 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 的问题,但我不知道如何解决。
Note: Debugging in Android Device
几件事。通常使用 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 都可以从基础继承,并且您不会在任何地方都有重复的代码。
*编辑:刚刚注意到您在 SchItem
class 中定义了 TapCommand
。在那里,每次该命令为 运行 时,您都会新建一个 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);
}
}
这是我的代码:
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 的问题,但我不知道如何解决。
Note: Debugging in Android Device
几件事。通常使用 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 都可以从基础继承,并且您不会在任何地方都有重复的代码。
*编辑:刚刚注意到您在 SchItem
class 中定义了 TapCommand
。在那里,每次该命令为 运行 时,您都会新建一个 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);
}
}