Search code examples
c#wpfasynchronousasync-awaitwpfdatagrid

Update/populate DataGrid with data asynchronously


I have checked some of topics and google but can't find proper solution. I want to make WPF application to download Items information to DataGrid (items columns) with TextBox (item name) using RestApi.

The code is correct and work but there's a problem with async updating DataGrid.

DataTable dt;
public DataTable Dt { get => dt; set { dt = value; dataGridItems.DataContext = Dt.DefaultView; } }

private async void ButtonSearch_Click(object sender, RoutedEventArgs e)
{
    //buttonSearch.IsEnabled = false;
    rest = new RestClass(ClientId, ClientSecret);

    Task T = Task.Run(() => SearchItem(rest, textBoxProductName.Text));

    T.ContinueWith((t) =>
       {
           dataGridItems.DataContext = Dt.DefaultView;
           //buttonSearch.IsEnabled = true;
       }, TaskScheduler.FromCurrentSynchronizationContext());

Above code with small changes (dataGridItems.DataBinding) worked in WinForms without any problems but I can't make it work in WPF application.

private void SearchItem(RestClass Rest, string ItemName)
{
    try
    {
        var x = Rest.GetTokenJ().Result;
        ItemsOffersWPF.Rootobject searchResponse = Rest.requestSearchItem(ItemName);
        GetItemsCollection(searchResponse);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    //dataGridItems.DataContext = Dt.DefaultView;
}

I have tried Invoke, InvokeAsync but it makes UI irresponsible which is what I want to avoid.


Solution

  • Ok thanks to you, I finally found solution. It's not perfect but works well. The problem was propably updating DataTable (Dt property) inside GetItemsCollection method and using textBoxProductName.Text inside await SearchItem function.

    // its useless now
    //DataTable Dt { get => dt; set { dt = value; dataGridAllegro.DataContext = Dt.DefaultView; } } 
    private async void ButtonSearch_Click(object sender, RoutedEventArgs e)
    {
       buttonSearch.IsEnabled = false;
       var productName = textBoxProductName.Text; // get Text value before using Task!
       await Task.Run(() => SearchItem(productName));
       dataGridItems.ItemsSource = dt.DefaultView;
       buttonSearch.IsEnabled = true;
    }     
    
    private async void SearchItem(string ProductName)
    {
       try
       {
          var x = rest.GetTokenJ().Result;
          ItemsOffersWPF.Rootobject searchResponse = rest.requestSearchItem(ProductName);
          GetItemsCollection(searchResponse); // inside update dt not property DataTable Dt { get => dt; set { dt = value; dataGridAllegro.DataContext = Dt.DefaultView; } }
       // = exception using another thread UI
       }
       catch(Exception ex)
       {
          MessageBox.Show(ex.Message);
       }  
    }