Лучший способ приостановить события управления в Windows Forms?
Это кажется очень простой и очень распространенной проблемой. Самый простой пример, который я могу придумать, это:
форма имеет пять флажков с флажком" check all/check none " над ними. Когда пользователь выбирает проверку всех флажков, я переключаю состояния "детей" - очевидно, я не хочу запускать события проверки всех детей, пока я не закончу установку всех флажков.
Я не могу найти событие управления приостановкой для всей формы. Если я просто скучаю ... крайне простой ответ. За исключением простого решения, которое мне просто не хватает, каков наилучший способ (лучшая практика? принятое решение?) приостановить события управления формой?
6 ответов
Я сталкивался с этим раньше и обычно видел, как люди делают это:
/*SNIP*/
private bool isMassUpdate;
public void Check1_Check(object sender, EventArgs e)
{
if(!isMassUpdate)
{
do some stuff
}
}
/*SNIP*/
вы также можете отсоединить и заново присоединить обработчики событий, однако, мне сказали, что это может быть источником утечки памяти.
информация об утечках памяти и обработчиках событий: они не связаны напрямую с присоединением и отсоединением, но мы видели в одном из наших приложений, что плохая ссылка на обработчики событий вниз по деревьям наследования может вызвать он.
Что я делаю в этих случаях вместо логического значения, которое приостанавливает события, я использую счетчик. Если счетчик > 0, то приостановить события, если счетчик = 0, а затем возобновить события. Это помогает с проблемой, если у меня есть несколько вещей, которые могут запросить приостановку событий.
другая полезная вещь, если мне нужно приостановить события в блоке, я создаю небольшой вспомогательный класс, который IDisposable, который я могу использовать в блоке" using " (в C#), поэтому я не забываю уменьшить счетчик, как только я выйду из поля зрения.
из вашего другого вопроса я собираюсь догадаться, что вы используете VB .Сеть. Итак, 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, чтобы вернуть обработчики событий. Если все флажки используют один и тот же обработчик, их можно поместить в коллекцию и выполнить цикл по коллекции для добавления или удаления обработчиков.
вы также можете рассмотреть возможность обработки событий "щелчка" для кнопок, а не проверки. Это может быть ближе к вашим намерениям.
см. вопрос переполнения стека Как игнорировать простые события при изменении состояний управления в C# Windows Forms?
в более общем случае, если у вас сложные отношения между элементами управления, вы можете проверить, какой элемент управления запустил событие, проверив его собственное сфокусированное свойство... каждый объект зависит только от самого себя.
в своем Visual Basic 6.0 приложение мне пришлось обрабатывать пользователей двойным щелчком все, поэтому во всех моих обработчиках событий у меня есть одна строка, которая проверяет глобальную переменную
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