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);
}
}
我检查了一些主题和 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);
}
}