WinPhone 8.1 |强制 xaml 布局更改
WinPhone 8.1 | Force xaml layout change
我有一个文本框,当用户按下回车键时,我们会执行 API 调用。但是在这段时间里,我想更新 XAML 布局以显示进度条。然而,布局更新仅在方法完成后发生,这意味着在我们进行搜索时没有进度条可见。
我们已经覆盖了 OnKeyDown 事件来处理用户按下回车键。
有没有办法在此方法中强制进行 XAML 布局更新?
protected override void OnKeyDown(KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter && (xaml_search_box.FocusState == Windows.UI.Xaml.FocusState.Pointer || xaml_search_box.FocusState == Windows.UI.Xaml.FocusState.Keyboard))
{
//We want to make the progressbar visible here
xaml_search_progressbar.Visibility = Windows.UI.Xaml.Visibility.Visible
//collapse keyboard
Windows.UI.ViewManagement.InputPane.GetForCurrentView().TryHide();
string _query = xaml_search_box.Text;
List<Task> tasks = new List<Task>();
//Long web request
Task t = Task.Run(() => APICall.BasicSearch(_query));
tasks.Add(t);
Task.WaitAll(tasks.ToArray());
m_results = APICall.m_basicsearch;
xaml_search_results.ItemsSource = m_results;
xaml_search_results_grid.ItemsSource = m_results;
}
base.OnKeyDown(e);
//Our layout is updated here, AFTER we have done the search making it pointless to show a loading bar
}
您需要将控制权交给 UI 线程,以便它有机会显示进度指示器。一种方便的方法是使用 async/await 关键字:
protected override async void OnKeyDown(KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter && (xaml_search_box.FocusState == Windows.UI.Xaml.FocusState.Pointer || xaml_search_box.FocusState == Windows.UI.Xaml.FocusState.Keyboard))
{
//We want to make the progressbar visible here
xaml_search_progressbar.Visibility = Windows.UI.Xaml.Visibility.Visible
//collapse keyboard
Windows.UI.ViewManagement.InputPane.GetForCurrentView().TryHide();
// Yield control to the UI thread
await Task.Delay(10);
string _query = xaml_search_box.Text;
List<Task> tasks = new List<Task>();
//Long web request
Task t = Task.Run(() => APICall.BasicSearch(_query));
tasks.Add(t);
Task.WaitAll(tasks.ToArray());
m_results = APICall.m_basicsearch;
xaml_search_results.ItemsSource = m_results;
xaml_search_results_grid.ItemsSource = m_results;
}
base.OnKeyDown(e);
//Our layout is updated here, AFTER we have done the search making it pointless to show a loading bar
}
就是说,您不应该在等待任务时阻塞 UI 线程。您应该使用 WhenAll
而不是 WaitAll
:
await Task.WhenAll(tasks.ToArray());
您不需要列表。只需等待 Task.Run() 调用。 await 将返回到 UI 线程并使进度条能够显示。很简单的。您还需要使事件处理程序异步。
await Task.Run(() => APICall.BasicSearch(_query));
您需要使被覆盖的方法与 protected override async void OnKeyDown(KeyRoutedEventArgs e)
异步,否则它会阻塞 UI 线程。如果可能,您还应该考虑将 APICall.BasicSearch 方法更改为异步方法,这样您就不需要像那样拆分任务,而是可以按照 m_results = await APICall.BasicSearch(_query);
[=12 的方式做一些事情=]
我有一个文本框,当用户按下回车键时,我们会执行 API 调用。但是在这段时间里,我想更新 XAML 布局以显示进度条。然而,布局更新仅在方法完成后发生,这意味着在我们进行搜索时没有进度条可见。
我们已经覆盖了 OnKeyDown 事件来处理用户按下回车键。
有没有办法在此方法中强制进行 XAML 布局更新?
protected override void OnKeyDown(KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter && (xaml_search_box.FocusState == Windows.UI.Xaml.FocusState.Pointer || xaml_search_box.FocusState == Windows.UI.Xaml.FocusState.Keyboard))
{
//We want to make the progressbar visible here
xaml_search_progressbar.Visibility = Windows.UI.Xaml.Visibility.Visible
//collapse keyboard
Windows.UI.ViewManagement.InputPane.GetForCurrentView().TryHide();
string _query = xaml_search_box.Text;
List<Task> tasks = new List<Task>();
//Long web request
Task t = Task.Run(() => APICall.BasicSearch(_query));
tasks.Add(t);
Task.WaitAll(tasks.ToArray());
m_results = APICall.m_basicsearch;
xaml_search_results.ItemsSource = m_results;
xaml_search_results_grid.ItemsSource = m_results;
}
base.OnKeyDown(e);
//Our layout is updated here, AFTER we have done the search making it pointless to show a loading bar
}
您需要将控制权交给 UI 线程,以便它有机会显示进度指示器。一种方便的方法是使用 async/await 关键字:
protected override async void OnKeyDown(KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter && (xaml_search_box.FocusState == Windows.UI.Xaml.FocusState.Pointer || xaml_search_box.FocusState == Windows.UI.Xaml.FocusState.Keyboard))
{
//We want to make the progressbar visible here
xaml_search_progressbar.Visibility = Windows.UI.Xaml.Visibility.Visible
//collapse keyboard
Windows.UI.ViewManagement.InputPane.GetForCurrentView().TryHide();
// Yield control to the UI thread
await Task.Delay(10);
string _query = xaml_search_box.Text;
List<Task> tasks = new List<Task>();
//Long web request
Task t = Task.Run(() => APICall.BasicSearch(_query));
tasks.Add(t);
Task.WaitAll(tasks.ToArray());
m_results = APICall.m_basicsearch;
xaml_search_results.ItemsSource = m_results;
xaml_search_results_grid.ItemsSource = m_results;
}
base.OnKeyDown(e);
//Our layout is updated here, AFTER we have done the search making it pointless to show a loading bar
}
就是说,您不应该在等待任务时阻塞 UI 线程。您应该使用 WhenAll
而不是 WaitAll
:
await Task.WhenAll(tasks.ToArray());
您不需要列表。只需等待 Task.Run() 调用。 await 将返回到 UI 线程并使进度条能够显示。很简单的。您还需要使事件处理程序异步。
await Task.Run(() => APICall.BasicSearch(_query));
您需要使被覆盖的方法与 protected override async void OnKeyDown(KeyRoutedEventArgs e)
异步,否则它会阻塞 UI 线程。如果可能,您还应该考虑将 APICall.BasicSearch 方法更改为异步方法,这样您就不需要像那样拆分任务,而是可以按照 m_results = await APICall.BasicSearch(_query);
[=12 的方式做一些事情=]