在WPF上单击UpdateLayout

时间:2012-03-01 15:49:46

标签: c# wpf

我有一个简单的页面,上面有一个按钮和一个标签。当我单击按钮时我想要更新标签文本,我已经复制了here

中的代码

然而,当我使用以下示例时。在功能完成之前,文本不会更新。有任何想法吗。 WPF窗口表格上有按钮和标签。

我在按钮按下后的代码中有以下内容,并且永远不会显示第一条消息。

Thread.Sleep表示从数据库中提取数据以返回到屏幕,这可能需要3到30秒的时间,因此我想让它能够向用户展示一些东西。

任何想法???

using System.Threading;
using System.Windows;
using System.Windows.Threading;

namespace NetSpot.RESV4.Presentation
{
   /// <summary>
   /// Interaction logic for Window1.xaml
   /// </summary>
   public partial class Window1 : Window
   {
       public Window1()
       {
           InitializeComponent();
       }

       private void button1_Click(object sender, RoutedEventArgs e)
       {
           label1.Content = "Button 1 Clicked";
           ForceUIToUpdate();
           Thread.Sleep(4000);
           label1.Content = "button 1 Updated";
       }

       public static void ForceUIToUpdate()
       {
           DispatcherFrame frame = new DispatcherFrame();
           Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Render, new     DespatcherOperationCallback(delegate(object parameter)
        {
            frame.Continue = false;
            return null;
        }), null);
        Dispatcher.PushFrame(frame);
    }

  }
}

3 个答案:

答案 0 :(得分:3)

如果您希望标签在4秒后更新,那么使用Dispatcher Timer可能会更好。

public partial class Window1 : Window
{
   readonly DispatcherTimer m_timer = new DispatcherTimer();
   public Window1()
   {
       InitializeComponent();

       m_timer.Interval = TimeSpan.FromSeconds(4);
       m_timer.Tick += TimerOnTick;
   }

   private void button1_Click(object sender, RoutedEventArgs e)
   {
       label1.Content = "Button 1 Clicked";
       m_timer.Start();
   }

   private void TimerOnTick(object sender, EventArgs eventArgs)
   {
       m_timer.Stop();
       label1.Content1 = ...
   }

答案 1 :(得分:2)

要直接回答您的问题(无论采用何种方法),您都不会在初始值更改后发信号通知UI应该更新。点击事件结束后,此信号自动发生。添加对label1.UpdateLayout()的调用,如下所示:

   private void button1_Click(object sender, RoutedEventArgs e)
   {
       label1.Content = "Button 1 Clicked";
       label1.UpdateLayout();
       ForceUIToUpdate();
       Thread.Sleep(4000);
       label1.Content = "button 1 Updated";
   }

现在您应该看到预期的行为。

编辑 - 尝试使用此版本的ForceUIToUpdate。

   public static void ForceUIToUpdate()
   {
       DispatcherFrame frame = new DispatcherFrame();
       Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Render, new     DispatcherOperationCallback(delegate(object parameter)
       {
           frame.Continue = false;
           return null;
       }), null);
       Dispatcher.PushFrame(frame);
   }

这会导致ForceUIToUpdate阻塞,直到帧通过渲染队列,这就是你真正想要的。

答案 2 :(得分:0)

尽量不要让当前线程进入睡眠状态,而只是通过调度程序设置另一个线程的值。

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        Task.Run(() =>
        {
            Dispatcher.Invoke(new Action(() =>
            {
                label1.Content = "Waiting";
            }), null);

            Thread.Sleep(2000);

            Dispatcher.Invoke(new Action(() =>
            {
                label1.Content = "Done";
            }), null);

        });
    }

希望这有帮助。

更新:使用async / await

    private async void button1_Click(object sender, RoutedEventArgs e)
    {
        label1.Content = "Waiting";

        await Task.Run(() => Thread.Sleep(2000));

        label1.Content = "Done";
    }