Лучший способ приостановить события управления в Windows Forms?
Вопрос
Кажется, это очень простая и очень распространенная проблема.Самый простой пример, который я могу придумать, это:
В форме имеется пять флажков с флажком «Отметить все/отметить ничего» над ними.Когда пользователь выбирает проверку всех флажков, я переключаю состояния «дочерних элементов» — очевидно, я не хочу запускать события проверки всех дочерних элементов, пока не закончу установку всех флажков.
Я не могу найти событие управления приостановкой всей формы.Если мне это просто не хватает, тогда отличный простой ответ.За исключением простого решения, которое мне просто не хватает, каков наилучший способ (лучшая практика?принятое решение?) приостановить события управления формой?
Решение
Я сталкивался с этим раньше и обычно видел, как люди делают это:
/*SNIP*/
private bool isMassUpdate;
public void Check1_Check(object sender, EventArgs e)
{
if(!isMassUpdate)
{
do some stuff
}
}
/*SNIP*/
Вы также можете отсоединить и снова подключить обработчики событий, однако мне сказали, что это может быть источником утечек памяти.
Информация об утечках памяти и обработчиках событий:Они не связаны напрямую с присоединением и отсоединением, но в одном из наших приложений мы видели, что это может быть вызвано неправильным обращением обработчиков событий к деревьям наследования.
Другие советы
Что я делаю в этих случаях вместо того, чтобы иметь логическое значение, которое приостанавливает события, я использую счетчик. Когда счет равен > 0, затем приостановить события, когда счетчик = 0, затем возобновить события. Это помогает решить проблему, если у меня есть несколько вещей, которые могут потребовать приостановки событий.
Еще одна полезная вещь: если мне нужно приостановить события в блоке, я создаю небольшой вспомогательный класс, который IDisposable, который я могу использовать в " using " блок (в C #), поэтому я не забываю уменьшить счетчик, как только я выйду из области видимости.
Из вашего другого вопроса, я собираюсь догадаться, что вы используете VB .NET. Итак, RemoveHandler - ваш лучший выбор. Обычно в VB люди устанавливают обработчики событий, используя предложение Handles. Но вы также можете сделать это следующим образом:
AddHandler chk1.CheckedChanged, AddressOf DoSomething
где DoSomething может выглядеть так:
Private Sub DoSomething(ByVal sender As Object, ByVal e As EventArgs)
' whatever
End Sub
AddHandler подключает событие, чтобы оно сработало. Чтобы он не срабатывал, используйте RemoveHandler:
RemoveHandler chk1.CheckedChanged, AddressOf DoSomething
Перед обновлением свойства Checked своих дочерних флажков вызовите RemoveHandler для каждого из них; затем, когда вы закончите, вызовите AddHandler, чтобы вернуть обработчики событий. Если все ваши флажки используют один и тот же обработчик, вы можете поместить их в коллекцию и пройтись по коллекции, чтобы добавить или удалить обработчики.
Можно также рассмотреть возможность обработки событий нажатия кнопок для кнопок, а не для проверки изменений. Это может быть ближе к вашим намерениям.
В моем Visual Basic 6.0 приложении мне приходилось обрабатывать пользователей, дважды щелкающих < em> все , поэтому во всех моих обработчиках событий у меня есть одна строка, которая проверяет глобальную переменную
Private bSuspendEvents as Boolean
Private Sub Button1_Click()
On Error Goto ErrorHandler
If bSuspendEvents then Exit Sub
bSuspendEvents = True
'Do stuff
NormalExit:
bSuspendEvents = False
Exit Sub
ErrorHandler:
'Handle Error
Resume NormalExit
End Sub
См. вопрос переполнения стека Как игнорировать простые события, возникающие при изменении состояний элементов управления в C # Windows Forms?
В более общем случае, если у вас сложные отношения между элементами управления, вы можете проверить, какой элемент управления вызвал событие, проверив свое собственное свойство Focused ... каждый объект зависит только от самого себя.