In my WPF project, I need to transfer large SQL data to a datagrid. Naturally, it waits for a long time. I used the MVVM pattern.
To make UI more responsive, I use a backgroundworker. But the screen freezes again and the UI is updated when the transfer is completed. I want the UI to be updated while loading data. There are topics about this subject, I understood it is about using ProgressChanged
event but I couldn’t figure it out. So I prepared a simple project for asking.
This is my XAML markup:
<Window x:Class="BackRoundWorkerTest.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:BackRoundWorkerTest"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:BackroundWorkerVM x:Key="vm"/>
</Window.Resources>
<Grid DataContext="{StaticResource vm}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<DataGrid ItemsSource="{Binding Persons, UpdateSourceTrigger=PropertyChanged}"
AutoGenerateColumns="True">
</DataGrid>
<Button Grid.Row="1"
Command="{Binding DoWorkCommand}"/>
</Grid>
</Window>
This is the view model:
public class BackgroundWorkerVM : INotifyPropertyChanged
{
private BackgroundWorker worker;
// it calls the PopulateList() method.
public DoWorkCommand DoWorkCommand { get; set; }
public BackgroundWorkerVM()
{
// it calls the PopulateList() method.
DoWorkCommand = new DoWorkCommand(this);
worker = new BackgroundWorker();
worker.DoWork += Worker_DoWork;
worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
worker.WorkerReportsProgress = true;
}
private ObservableCollection<Person> persons = new ObservableCollection<Person>();
public ObservableCollection<Person> Persons
{
get { return persons; }
set
{
persons = value;
OnPropertyChanged();
}
}
public void PopulateList()
{
worker.RunWorkerAsync();
}
private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
}
private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
App.Current.Dispatcher.Invoke((Action)delegate
{
for (int i = 0; i < 100; i++)
{
Persons.Add(new Person { PersonName = "john", Surname = "Smith", ResultChanged = true });
Thread.Sleep(100);
Persons.Add(new Person { PersonName = "jack", Surname = "Smith", ResultChanged = false });
}
});
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
This is the model class:
public class Person
{
public string PersonName { get; set; }
public string Surname { get; set; }
public bool ResultChanged { get; set; }
}