循环删除时ListView不刷新

ListView doesnt refresh while deleting in a loop

我有一个要绑定到 ObservableCollectionListView。当我手动删除项目时(每个按钮事件),项目被删除并且 ListView 立即刷新。

当我在 for loop 中删除项目时,只有列表在操作结束时刷新,在所有元素都被删除之后。在删除项目之前,对它们进行一些耗时的操作,并在另一个 ListView.

中通知用户

那么如何实现,每次删除一个项目后列表都会刷新。

问题不在于如何从列表中循环删除项目,因为这有效(以相反的顺序)。问题是,为什么UI在删除项目时不刷新。

这里我有简化的示例代码,它显示了这种行为:

Xaml

<Window x:Class="ListViewTest.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:ListViewTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
        </Grid.RowDefinitions>

        <ListView ItemsSource="{Binding LstFiles}" Grid.Column="0" Grid.Row="0"/>
        <Button Content="Los" Name="losBtn" Click="losBtn_Click" Grid.Column="0" Grid.Row="1" />
        <Button Content="del" Name="delBtn" Click="delBtn_Click" Grid.Column="0" Grid.Row="2" />
    </Grid>
</Window>

C#后面

using System.Collections.ObjectModel;
using System.Windows;

namespace ListViewTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public ObservableCollection<string> LstFiles { get; set; }
        public MainWindow()
        {
            InitializeComponent();
            LstFiles = new ObservableCollection<string>();

            for (int i = 0; i < 20; i++)
            {
                LstFiles.Add(string.Format("file_{0}", i));
            }

            DataContext = this;
        }

        private  void losBtn_Click(object sender, RoutedEventArgs e)
        {

            for (int i = LstFiles.Count - 1; i >= 0; i--)
            {
                LstFiles.RemoveAt(i);
                System.Threading.Thread.Sleep(50);
            }   
        }

        private void delBtn_Click(object sender, RoutedEventArgs e)
        {
            LstFiles.RemoveAt(0);
        }
    }
}

sleep是为了模拟耗时操作。

why is the ui not refreshing while deleting the items

这是因为您正在调用 Thread.Sleep(),它只会阻塞 UI 线程。您绝不能在 UI 应用程序中调用它。

虽然不清楚您为什么想要这个 "delete loop"(而不是仅仅清除 ObservableCollection),但您可以在 async 单击处理程序中使用 Task.Delay() 而不是 Sleep方法:

private async void losBtn_Click(object sender, RoutedEventArgs e)
{
    for (int i = LstFiles.Count - 1; i >= 0; i--)
    {
        LstFiles.RemoveAt(i);
        await Task.Delay(50);
    }   
}

如果不是简单的延迟而是要调用一些耗时的操作,您可以简单地将其包装在 Task.Run 调用中:

private async void losBtn_Click(object sender, RoutedEventArgs e)
{
    for (int i = LstFiles.Count - 1; i >= 0; i--)
    {
        LstFiles.RemoveAt(i);
        await Task.Run(() =>
        {
            // some long running operation
        });
    }   
}