【问题标题】:WinPhone 8.1 | Force xaml layout change手机8.1 |强制 xaml 布局更改
【发布时间】:2015-06-09 23:42:54
【问题描述】:

我有一个文本框,当用户按下回车键时,我们执行 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
    }

【问题讨论】:

    标签: c# xaml windows-phone-8.1 win-universal-app


    【解决方案1】:

    您需要将控制权交给 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());
    

    【讨论】:

    • await Task.Delay(10); 完全不需要。
    【解决方案2】:

    您不需要列表。只需等待 Task.Run() 调用。 await 将返回给 UI 线程并显示进度条。很简单。您还需要使事件处理程序异步。

    await Task.Run(() => APICall.BasicSearch(_query));
    

    【讨论】:

      【解决方案3】:

      你需要让被覆盖的方法与protected override async void OnKeyDown(KeyRoutedEventArgs e)异步,否则会阻塞UI线程。如果可能的话,您还应该考虑将 APICall.BasicSearch 方法更改为异步方法,这样您就不需要像这样分离任务,而是可以按照m_results = await APICall.BasicSearch(_query); 的方式做一些事情

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多