ListView не обновляется при удалении в цикле - PullRequest
0 голосов
/ 15 февраля 2019

У меня есть ListView, который должен связываться с ObservableCollection.Когда я удаляю элементы вручную (по событию кнопки), элементы удаляются, и ListView немедленно обновляется.

Когда я удаляю элементы в цикле , только списокобновляется в конце операции, после удаления всех элементов.Перед удалением элементов выполняются некоторые трудоемкие операции с ними, а также уведомление пользователя в другом ListView.

Так как этого можно достичь, чтобы список обновлялся после каждого отдельного удаленияэлемента.

Вопрос не в том, как удалить элементы в цикле из списка, потому что это работает (в обратном порядке).Вопрос в том, почему пользовательский интерфейс не обновляется при удалении элементов.

Здесь я упростил пример кода, который демонстрирует это поведение:

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);
        }
    }
}

Режим сна предназначен для имитации трудоемких операций.

1 Ответ

0 голосов
/ 15 февраля 2019

почему пользовательский интерфейс не обновляется при удалении элементов

Это потому, что вы вызываете Thread.Sleep(), который просто блокирует поток пользовательского интерфейса.Вы никогда не должны вызывать это в приложении пользовательского интерфейса.

Хотя неясно, зачем вообще нужен этот «цикл удаления» (вместо простой очистки ObservableCollection), вы можете использовать Task.Delay() вместо Sleep inметод обработки async Click:

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
        });
    }   
}
...