Update/populate 具有异步数据的 DataGrid

Update/populate DataGrid with data asynchronously

我检查了一些主题和 google 但找不到合适的解决方案。 我想让 WPF 应用程序使用 RestApi 使用 TextBox(项目名称)将项目信息下载到 DataGrid(项目列)。

代码正确且有效,但异步更新 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());

以上代码稍作改动 (dataGridItems.DataBinding) 在 WinForms 中运行没有任何问题,但我无法使其在 WPF 应用程序中运行。

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

我尝试过 Invoke、InvokeAsync,但它 UI 不负责任,这是我想避免的。

你应该使用 await 而不是 T.ContinueWith

    await Task.Run(() => SearchItem(rest, textBoxProductName.Text));
    dataGridItems.DataContext = Dt.DefaultView;

"await" 之后的任何内容都将在任务完成后立即执行 运行。

好的,多亏了你,我终于找到了解决办法。它并不完美,但效果很好。 问题可能是在 GetItemsCollection 方法中更新 DataTable (Dt 属性) 并在 await SearchItem 函数中使用 textBoxProductName.Text。

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