Невозможно включить отключенный элемент управления в том же блоке - PullRequest
1 голос
/ 03 апреля 2012

У меня есть следующий код. Внутри того же блока кода я отключаю элемент управления, затем включаю его, но он, похоже, не работает и остается в исходном состоянии IsEnable.

// Button never enable
public void Foo()
{
   button1.IsEnabled = false
   Thread.Sleep(3000);
   button1.IsEnabled = true;
   Thread.Sleep(3000);
   button1.IsEnabled = false;
}

Ответы [ 4 ]

4 голосов
/ 03 апреля 2012

Прежде всего: не странно, что кнопка не активируется после выполнения метода Foo, так как последняя строка отключает кнопку.

Если вы хотите «увидеть»Изменение состояния кнопки включено, вам нужно обработать сообщения окна перед сном.Thread.Sleep вызывает поток пользовательского интерфейса в спящем режиме, поэтому обновления пользовательского интерфейса не будут.Что вам нужно сделать, это заставить приложение обрабатывать все ожидающие сообщения окна.

public static void DoEvents()
{
    if (Application.Current != null)
        Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new ThreadStart(delegate { }));
}

public void Foo()
{
   button1.IsEnabled = false
   DoEvents();
   Thread.Sleep(3000);

   button1.IsEnabled = true;
   DoEvents();
   Thread.Sleep(3000);

   button1.IsEnabled = false;
}

РЕДАКТИРОВАТЬ
Дальнейшее объяснение:

Когда первый Thread.Sleepвызвана, кнопка отключена (IsEnabled is false).Затем, подождав 3 секунды, вы устанавливаете кнопку в положение «включено», а после этого снова отключаете ее.Кнопка фактически находится в этом состоянии, но визуальной обратной связи нет (например, если вы посмотрите на форму, кнопка не будет мигать).

Это потому, что вы блокируетеUI поток по телефону Thread.Sleep.Это препятствует тому, чтобы окно получало оконные сообщения, которые сообщают окну, когда перерисовывать себя или одного из его дочерних элементов (кнопка не «знает», что она должна быть серой).

Таким образом, вам нужно дать окновозможность получать сообщения и обновлять своих детей.В приложениях Windows Forms это было сделано с помощью Application.DoEvents, который обрабатывал все ожидающие сообщения окна.

В WPF нет такой вещи, как Application.DoEvents, но код, который я разместил, эмулирует это, вызывая Thread, которая ничего не делает, но этого небольшого промежутка времени между изменением включенного состояния кнопки и блокировкой потока пользовательского интерфейса достаточно для перекрашивания элемента управления кнопки.

1 голос
/ 03 апреля 2012

Когда вы вызываете sleep, текущий поток приостанавливается, и пользовательский интерфейс будет зависать (когда вы пытаетесь щелкнуть по нему, он будет недоступен) до тех пор, пока поток не будет пробужден.Таким образом, поток спит в течение 6 секунд, и вы не заметите, что кнопка была включена.В конце кнопка остается отключенной.

Вы должны запустить свой код в другом потоке с помощью диспетчера.

0 голосов
/ 18 октября 2013

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

NET предоставляет ряд параметров потоков, таких как BackgroundWorker, Thread, ThreadPool и т. Д.

Более новая платформа NET также предоставляет метод async / await, позволяющий потоку GUI выполнять другую работу во время события.

0 голосов
/ 03 апреля 2012

Вы когда-нибудь думали, что вы можете быть в UI-Thread?Читайте о диспетчере в wpf .

...