2012-04-03 2 views
1

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

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

ответ

4

Прежде всего: не так странно, что кнопка не активирована после того, как метод 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; 
} 

EDIT
Дальнейшее объяснение:

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

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

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

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

+0

+1 работал. Но объяснение непонятно. После первого завершения Thread.Sleep кнопка должна быть включена до второго Thread.Sleep. Я все равно должен заметить изменение состояния кнопки. нет? – KMC

+0

Я добавил несколько объяснений. –

+0

Спасибо, но хм ... как только первый Thread.Sleep заканчивается, пользовательский интерфейс должен быть разблокирован, чтобы визуальная обратная связь до второго Thread.Sleep блокирует интерфейс. Поэтому я до сих пор не вижу, как кнопка не мигает. – KMC

1

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

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

0

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

NET действительно обеспечивает ряд опций пронизывающих как BackgroundWorker, Thread, ThreadPool и т.д.

Поздние рамки NET также обеспечивают асинхронный/ОЖИДАНИЕ метод позволяют GUI нити делать другую работу во время мероприятия.