I am trying to make an asynchronous call to load data into my grid. The problem is that the operation blocks the user interface (it works in the main thread) - and I do not know why. I am trying to do this to get data in the background ... Here is the code:
Binding the ViewModel class to the DataContext of the main window:
<Window.DataContext>
<vm:MainWindowViewModel WindowTitle="MVVM" BtnLoadText="LOAD DATA"/>
</Window.DataContext>
DataGrid with column binding to the collection property (PeopleList) in the ViewModel class:
<DataGrid AutoGenerateColumns="False" IsReadOnly="True" ItemsSource="{Binding Path=PeopleList, Mode=TwoWay}" Margin="5">
<DataGrid.Columns>
<DataGridTextColumn Header="First name" Binding="{Binding Path=FirstName}"/>
<DataGridTextColumn Header="Last name" Binding="{Binding Path=LastName}"/>
<DataGridTextColumn Header="Age" Binding="{Binding Path=Age}"/>
</DataGrid.Columns>
</DataGrid>
<Button x:Name="btn_LoadData" Margin="5" Grid.Row="1" Content="{Binding Path=BtnLoadText}" Click="btn_LoadData_Click"/>
The code behind MainWindow is to trigger an asynchronous button click event:
public partial class MainWindow : Window
{
private MainWindowViewModel mainWindowViewModel;
public MainWindow()
{
InitializeComponent();
mainWindowViewModel = (MainWindowViewModel)DataContext;
}
private async void btn_LoadData_Click(object sender, RoutedEventArgs e)
{
await mainWindowViewModel.LoadData();
}
}
ViewModel class responsible for MainWindow:
class MainWindowViewModel
{
public string WindowTitle { get; set; }
public string BtnLoadText { get; set; }
public ObservableCollection<Person> PeopleList { get; set; }
private Database database = new Database();
public MainWindowViewModel()
{
PeopleList = new ObservableCollection<Person>();
}
public async Task LoadData()
{
PeopleList.Clear();
var result = await database.GetPeopleListLongOperationAsync();
PeopleList.Add(result.First());
}
}
As you can see, I make an asynchronous call using the LoadData method, which gets the data from the database and adds it to the ObservableCollection, which updates the DataGrid (binding to the DataGrid)
, "" :
public class Database
{
public IEnumerable<Person> GetPeopleListLongOperation()
{
Thread.Sleep(5000);
yield return new Person() { FirstName = "Name", LastName = "LastName", Age = new Random().Next(18, 40) };
}
public Task<IEnumerable<Person>> GetPeopleListLongOperationAsync()
{
return Task.Run<IEnumerable<Person>>(() =>
{
return GetPeopleListLongOperation();
});
}
}
Task.Run . , .
? , ...
IEnumerable to List . - , ?
public Task<List<Person>> GetPeopleListLongOperationAsync()
{
return Task.Run<List<Person>>(() =>
{
return GetPeopleListLongOperation().ToList();
});
}