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 的方式做一些事情=]