I have a ListView
which is to bind to an ObservableCollection
. When i delete items manually (per button event), the items are getting removed and the ListView
gets refreshed immediately.
When i delete the items in a for loop, only the list is getting refreshed at the end of the operation, after all elements are deleted. Before the items are getting deleted, there are some time-consuming operations on them and also notification to the user in another ListView
.
So how can it be achieved, that the list gets refreshed after every single deletion of an item.
The question is not, how to delete items in a loop from an list, because this works (in reverse order). The question is, why is the UI not refreshing while deleting the items.
Here i have simplified sample code, which is showing this behaviour:
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# behind
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);
}
}
}
The sleep is for simulating the time-consuming operations.
why is the ui not refreshing while deleting the items
This is because you are calling Thread.Sleep()
, which simply blocks the UI thread. You must never call that in a UI application.
While it's unclear why you want to have this "delete loop" at all (instead of just clearing the ObservableCollection), you may use Task.Delay()
instead of Sleep in an async
Click handler method:
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);
}
}
If instead of a simple delay there is some time-consuming operation to be invoked, you may simply wrap that in a Task.Run
call:
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
});
}
}