Лучший способ приостановить события управления в 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