Как предотвратить запуск событий с измененным значением при инициализации формы в .NET? - PullRequest
19 голосов
/ 30 июня 2010

Рассмотрим простую форму .NET с парой переключателей и флажком.

Каждая из переключателей имеет настройку обработчика CheckedChanged, которая выполняет некоторые действия в зависимости от состояния флажка.

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

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

Что я могу сделать, чтобы этот обработчик не запускал свой код?

Ответы [ 10 ]

28 голосов
/ 30 июня 2010

Чтобы сделать его немного менее грязным, если вы инициализируете элементы управления в конструкторе формы, вы можете использовать свойство IsHandleCreated вместо своего собственного bool, чтобы проверить, действительно ли оно должно проверятьсяили нет.
Я бы подумал, что обычно вы не захотите проверять что-либо до того, как это будет показано впервые, и дескриптор не будет создан, пока не будет.

Пример кода:

Private Sub myRadioButton_CheckedChanged(sender As Object, e As EventArgs) Handles myRadioButton.CheckedChanged
If myRadioButton.Checked AndAlso myRadioButton.IsHandleCreated Then
    'Do Work
End If
End Sub
20 голосов
/ 30 июня 2010

«Я также могу поставить логическое поле, для которого не установлено значение true, пока форма не будет полностью загружена, и не обрабатывать события, если это ложно, но это грязный хак».лучший способ сделать это!

Допустим, .NET предоставляет удобный способ включать и выключать все обработчики событий, пока форма не будет загружена.Даже те, с которыми ВЫ обращаетесь.Это все еще не будет достаточно гибким, чтобы отключить то, что вы хотели включить, но отключить то, что вы не сделали.Часто происходят настройки формы, и вы хотите, чтобы события запускались.Также форма не будет построена правильно, если нет событий.

3 голосов
/ 30 июня 2010

Простое решение - объявить инициализирующую переменную:

  Private Initializing as boolean = True

  Private Sub rb_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles rbNuevos.CheckedChanged, RbDesaparecidos.CheckedChanged, RbModificados.CheckedChanged, RbNoDesap.CheckedChanged, RbDesHoy.CheckedChanged, RbChT.CheckedChanged
      if Initializing then return

      'Your Code    
  End Sub

  Public Sub New()

       ' Llamada necesaria para el Diseñador de Windows Forms.
       InitializeComponent()    
       ' Agregue cualquier inicialización después de la llamada a InitializeComponent().

       initializing = false
  end sub

Самое сложное: уберите «метки» из метода и используйте AddHandler в новом методе.

  Public Sub New()

       ' Llamada necesaria para el Diseñador de Windows Forms.
       InitializeComponent()    
       ' Agregue cualquier inicialización después de la llamada a InitializeComponent().

       AddHandler RbChT.CheckedChanged, AddressOf rb_CheckedChanged
  end sub
2 голосов
/ 07 марта 2016

Для radiobutton см. Ответ Ханса Олссона

Для числового увеличения вниз, сделайте это следующим образом

Private Sub myNumeric_ValueChanged(sender As Object, e As EventArgs) Handles myNumeric.ValueChanged
        If myNumeric.Value >= 0 AndAlso myNumeric.IsHandleCreated Then
            'Do the work
        End If
End Sub

Ключевое слово myNumeric.Value и IsHandleCreated

1 голос
/ 05 июня 2014

Еще один способ:

Private Sub dgvGroups_CellValueChanged(sender As System.Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvGroups.CellValueChanged

    If Me.Visible = False Then Exit Sub ' Sub gets called on form load which causes problems

    wksGroups.Cells(e.RowIndex + 1, 1) = dgvGroups.Item(e.ColumnIndex, e.RowIndex).Value
    wksGroups.Cells(1, 5) = dgvGroups.RowCount
0 голосов
/ 18 июня 2018
  1. Не устанавливайте флажок для элемента управления, который действительно имеет большое значение в конструкторе.
  2. Глобальный флаг и условные выходы, где это необходимо.
  3. Попробуйте ... Поймать больные места, чтобыигнорировать бессмысленное исключение.

(Использование VS 2017) Мне кажется, что это раздражение, а не ошибка.Это соответствует используемой модели.Событие вызывается нормальной работой кода, но код, который я не написал (но могу получить доступ там, где дураки боятся наступить) и где, как кажется, нет (приличного) места ранее в нормальном потоке, чтобы предвидеть это.

Самым чистым ответом, похоже, не является проверка переключателей или переключателей в конструкторе вообще, если они вызывают какой-либо значимый код.Вместо этого эти элементы управления должны быть изменены кодом (например, флажок = истина) в событии Load (например) ПОСЛЕ всей инициализации.

Здесь нет потери гибкости, поскольку оба исправлены до сборки, только в разных местах.Обработчики событий будут обрабатывать его точно так же, как если бы пользователь щелкнул элемент управления в естественном потоке хорошо разработанного приложения с графическим интерфейсом.(Это напоминает мне древнюю пословицу RPG «Не сопротивляйся циклу». (Кто-нибудь здесь помнит RPG? Я, не являющаяся частью IBM-ориентированной команды, никогда не использовал ее, но имел интересные дискуссии с некоторыми из них.) Предварительная проверкаэлементы управления попадают в неправильную часть цикла VS.)

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

Еще одна вещь, которую я пробовал, прежде чем я решил, что проблема с заданными на уровне конструктора проверками была проблемой, и была очень приемлемая альтернатива - поместить опасные места в Try..Catch, чтобы иметь возможностьигнорировать исключениеТакже кладжа.

0 голосов
/ 26 февраля 2017

На тот случай, если кто-то все еще ищет это, событие инициируется при инициализации формы, НО форма еще не видна. Также скажем, что у вас есть связь с внешним ключом, для которой у вас есть значение по умолчанию, которое возникает при каждомобновление строки тоже.Поэтому следующий код работал для меня ....

    if (Visible && !(e.ColumnIndex == 0))
        {
            phoneEdited = true;
            MessageBox.Show("A Phone entry has been entered");
        }
0 голосов
/ 11 февраля 2014

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

0 голосов
/ 30 ноября 2013

Я положил публичную переменную в файл Module1 Dim Public bolForm_LoadingTF as Boolean = True

В каждом событии formLoad я ставлю bolForm_LoadingTF = True

В каждом элементе управления с OnSelectedIndexChanged событие, которое я ставлю, если bolForm_LoadingTF = True, тогда Exit Sub

В конце события загрузки формы я помещаю bolForm_LoadingTF = False

Возможно, я нарушаю кучу правил, но это работает для меня.

0 голосов
/ 05 июля 2012

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

Для этого вы можете просто перейти к сгенерированному коду формы, найденному в файле конструктора этой формы, и извлечь строки, которые добавляют событие.Это будет выглядеть примерно так:

this.controlName.CheckedChanged += new System.EventHandler(this.controlName_CheckedChanged);

Затем поместите все эти вызовы в метод, который вы вызываете после вызова InitializeComponent в конструкторе вашей формы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...