如何在删除项目后更新 ListView?

How to update a ListView after deleting an item?

在我的应用程序中,我从垃圾桶按钮中的 ListView 拖放了一个项目,它删除了该项目。要查看更改,我必须返回一个页面,然后再次打开下一页才能看到该项目已被删除。我想要的是当我将项目放到垃圾桶按钮时同时显示更新。

使用我现在拥有的代码,当我转到页面时 ListView 加载一秒钟然后消失。

谁能告诉我如何解决这个问题? 这是我的代码:

public sealed partial class BasketPage : Page, INotifyPropertyChanged
{

    private MobileServiceCollection<Information, Information> tempItem;
    private ObservableCollection<Information> items;
    private ObservableCollection<Information> RefreshedItems { get; set; }
    private IMobileServiceTable<Information> informationTable = App.MobileService.GetTable<Information>();
    private Information selectedInformation;


    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public BasketPage()
    {
        this.InitializeComponent();
        this.items = new ObservableCollection<Information>();
        this.refreshedItems = new ObservableCollection<Information>();

    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        getListData();

        base.OnNavigatedTo(e);
    }

    private async void getListData()
    {
        var query = App.conn.Table<Information>();

        foreach (var item in query)
        {

            tempItem = await informationTable
                .Where(todoItem => todoItem.Id == item.Name)
                .ToCollectionAsync();

            RefreshedItems.Add(tempItem.ElementAt(0));
        }           
    }
     private void BackButton_Click(object sender, RoutedEventArgs e)
    {
        if (Frame.CanGoBack)
        {
            Frame.GoBack();
        }
    }

    private void CollectedItemsListView_ItemClick(object sender, ItemClickEventArgs e)
    {
        selectedInformation = (Information)e.ClickedItem;

        Frame.Navigate(typeof(MediaViewPage), selectedInformation);
    }

    private void CollectedItemsListView_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
    {
        var item = string.Join(",", e.Items.Cast<Information>().Select(i => i.Id));
        e.Data.SetText(item);
        e.Data.RequestedOperation = DataPackageOperation.Move;
    }

    private void TrashButton_DragOver(object sender, DragEventArgs e)
    {
        if (e.DataView.Contains(StandardDataFormats.Text))
        {
            e.AcceptedOperation = DataPackageOperation.Move;
        }
    }

    private async void TrashButton_Drop(object sender, DragEventArgs e)
    {
        if (e.DataView.Contains(StandardDataFormats.Text))
        {
            var id = await e.DataView.GetTextAsync();
            var query = App.conn.Table<Information>();
            var itemToDelete = query.Where(p => p.Name == id).FirstOrDefault();

            RefreshedItems.Remove(itemToDelete);

            App.conn.Delete(itemToDelete);
            App.conn.Commit();   
        }
    }
}

这是我在 XAML 文件中所做的绑定:

 <ListView x:Name="CollectedItemsListView"
                  ItemsSource="{Binding refreshedItems}"
...

问题是 viewModel 是直接从模型中删除的,而不是它本身

我建议进行以下更改

首先,您需要在删除过程 (refreshedItems) 中删除或刷新您的一个 ObservableCollections,然后这将立即通知绑定到它的任何对象发生了更改

所以删除 CollectedItemsListView.ItemsSource = refreshedItems; 并改为更新集合

refreshedItems.Remove(deletedItem);

其次从 ObservableCollection 属性中删除所有 setter,您需要更新集合的内容而不是替换集合

public sealed partial class BasketPage : Page, INotifyPropertyChanged
{
    private MobileServiceCollection<Information, Information> tempItem;
    private ObservableCollection<Information> Items{get;private set;}
    private ObservableCollection<Information> RefreshedItems{get;private set;}
    private IMobileServiceTable<Information> informationTable = App.MobileService.GetTable<Information>();
    private Information selectedInformation;


    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public BasketPage()
    {
        this.InitializeComponent();
        this.Items = new ObservableCollection<Information>();
        this.RefreshedItems = new ObservableCollection<Information>();

    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        getListData();

        base.OnNavigatedTo(e);
    }

    private async void getListData()
    {
        var query = App.conn.Table<Information>();

        foreach (var item in query)
        {

            tempItem = await informationTable
                .Where(todoItem => todoItem.Id == item.Name)
                .ToCollectionAsync();

            RefreshedItems.Add(tempItem.ElementAt(0));

        }
    }

    private void BackButton_Click(object sender, RoutedEventArgs e)
    {
        if (Frame.CanGoBack)
        {
            Frame.GoBack();
        }
    }

    private void CollectedItemsListView_ItemClick(object sender, ItemClickEventArgs e)
    {
        selectedInformation = (Information)e.ClickedItem;

        Frame.Navigate(typeof(MediaViewPage), selectedInformation);
    }

    private void CollectedItemsListView_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
    {
        var item = string.Join(",", e.Items.Cast<Information>().Select(i => i.Id));
        e.Data.SetText(item);
        e.Data.RequestedOperation = DataPackageOperation.Move;
    }

    private void TrashButton_DragOver(object sender, DragEventArgs e)
    {
        if (e.DataView.Contains(StandardDataFormats.Text))
        {
            e.AcceptedOperation = DataPackageOperation.Move;
        }
    }

    private async void TrashButton_Drop(object sender, DragEventArgs e)
    {
        if (e.DataView.Contains(StandardDataFormats.Text))
        {
            var id = await e.DataView.GetTextAsync();
            var query = App.conn.Table<Information>();
            var itemToDelete = query.Where(p => p.Name == id).FirstOrDefault();

            RefreshedItems.Remove(itemToDelete);
            App.conn.Delete(itemToDelete);
            App.conn.Commit();   
        }
    }
}

编辑:由于您在此处建议的更改方面遇到问题,因此这是一个完整的工作示例

XAML

<Window x:Class="CollectionBindingDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CollectionBindingDemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:CollectionList x:Name="CollectionList"/>
    </Window.DataContext>
    <StackPanel>
        <Button Click="Add_Click">add</Button>
        <Button Click="Remove_Click">remove</Button>
        <ListView x:Name="ListVeiw" ItemsSource="{Binding IntegerNumbers}"/>
    </StackPanel>
</Window>

代码隐藏

namespace CollectionBindingDemo
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Add_Click(object sender, RoutedEventArgs e)
        {
            CollectionList.Add();
        }

        private void Remove_Click(object sender, RoutedEventArgs e)
        {
            var i = ListVeiw.SelectedItem as int?;
            if(i.HasValue)
                CollectionList.Remove(i.Value);
        }
    }
}

视图模型

namespace CollectionBindingDemo
{
    public class CollectionList
    {
        private Random rnd = new Random();
        public ObservableCollection<int> IntegerNumbers { get; } = new ObservableCollection<int>();


        public void Add()
        {
            IntegerNumbers.Add(rnd.Next(1000));
        }
        public void Remove(int i)
        {
            IntegerNumbers.Remove(i);
        }
    }
}