用数据异步更新/填充DataGrid

时间:2019-01-28 07:39:25

标签: c# wpf asynchronous async-await wpfdatagrid

我已经检查了一些主题和Google,但是找不到合适的解决方案。 我想让WPF应用程序使用RestApi使用TextBox(项目名称)将Items信息下载到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不负责任,这是我要避免的事情。

2 个答案:

答案 0 :(得分:0)

您应该使用await代替T.ContinueWith

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

任务完成运行后,将立即执行“等待”之后的所有操作。

答案 1 :(得分:0)

好的,谢谢,我终于找到了解决方案。它并不完美,但效果很好。 问题在于可能是在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);
   }  
}