Обновление / заполнение DataGrid данными асинхронно - PullRequest
0 голосов
/ 28 января 2019

Я проверил некоторые темы и Google, но не могу найти правильное решение.Я хочу, чтобы приложение WPF загружало информацию об элементах в DataGrid (столбцы элементов) с помощью TextBox (имя элемента) с помощью RestApi.

Код правильный и работает, но существует проблема с асинхронным обновлением 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, но этоделает пользовательский интерфейс безответственным, чего я хочу избежать.

Ответы [ 2 ]

0 голосов
/ 28 января 2019

Хорошо, благодаря вам, я наконец нашел решение.Это не идеально, но работает хорошо.Проблема заключалась в корректном обновлении DataTable (свойство Dt) внутри метода GetItemsCollection и использовании textBoxProductName.Text внутри функции await SearchItem.

// 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);
   }  
}
0 голосов
/ 28 января 2019

Вы должны использовать await вместо T.ContinueWith

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

все, что после "await" будет выполнено, как только задача завершится.

...