UpdateLayout на клик WPF - PullRequest
       3

UpdateLayout на клик WPF

2 голосов
/ 01 марта 2012

У меня есть простая страница с кнопкой и надписью на ней. Когда я нажимаю кнопку, чтобы обновить текст метки, я скопировал код с здесь

Однако, когда я использую следующий пример. Текст не обновляется, пока функция не будет завершена. Есть идеи. Форма окна 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 ]

3 голосов
/ 01 марта 2012

Если вы хотите, чтобы метка обновлялась через 4 секунды, вам, вероятно, лучше воспользоваться таймером диспетчера.

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 = ...
   }
2 голосов
/ 01 марта 2012

Чтобы ответить на ваш вопрос напрямую (независимо от методологии), вы никогда не сообщаете интерфейсу, что он должен обновляться после изменения начального значения. Этот сигнал появляется автоматически после завершения события щелчка. Добавьте вызов к 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 до тех пор, пока фрейм не пройдет через очередь рендеринга, что на самом деле и нужно.

0 голосов
/ 20 апреля 2015

Старайтесь не переводить текущий поток в спящий режим, вместо этого просто задайте значение другого потока через диспетчер.

    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 /жду

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

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

        label1.Content = "Done";
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...