Изменить: это другая проблема, чем та, которая рассматривается в этом предлагаемом дубликате. Этот вопрос касается другой проблемы, и ни один из ответов не применим к моей ситуации. Моя радиокнопка проверяется с самого начала, как и должно быть. Он (точнее, член его группы) устанавливается с использованием сохраненного свойства во время обработчика события Load. Кроме того, как указано ниже, мой проблемный переключатель НЕ является первым в порядке табуляции.
Я только что начал сталкиваться с проблемой в приложении WinForms, которое мне поручили рефакторинг.
Через некоторое время после завершения обработчика события Load формы автоматически срабатывает событие Click одной конкретной радиокнопки. Я не могу понять, почему, и это портит ожидаемый поток программы.
Я поставил точку останова в начале обработчика кликов и проверил стек вызовов, но проблемный вызов всегда исходит из внешнего кода, последние две строки которого — RadioButton.OnEnter, за которым следует Control.OnClick
Поиск в Google нашел этот ответ SE, но он не совсем соответствует моей ситуации. Неправильный переключатель находится довольно поздно в порядке табуляции, все элементы управления добавляются в VS Designer, а не кодом, а обработчик загрузки устанавливает фокус на другой элемент управления прямо перед его завершением. Между концом обработчика загрузки и ошибочным щелчком не встречается ссылка на переключатель (проверено с использованием слишком большого количества точек останова).
Кто-нибудь знает, что еще может привести к автоматическому щелчку элемента управления при запуске?
Редактировать
Вот код дизайнера для переключателя (mVmOff) и вложенных групповых полей, в которых он находится:
//
// mVmGroup (6th in tab order)
//
this.mVmGroup.Controls.Add(this.milliVmGroup);
this.mVmGroup.Controls.Add(this.mVRLabel);
this.mVmGroup.Controls.Add(this.mVmLabel);
this.mVmGroup.Controls.Add(this.mVRCombo);
this.mVmGroup.Controls.Add(this.mVm);
this.mVmGroup.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.mVmGroup.ForeColor = System.Drawing.Color.Black;
this.mVmGroup.Location = new System.Drawing.Point(200, 295);
this.mVmGroup.Name = "mVmGroup";
this.mVmGroup.Size = new System.Drawing.Size(169, 140);
this.mVmGroup.TabIndex = 6;
this.mVmGroup.TabStop = false;
this.mVmGroup.Text = "mV Meter";
this.toolTip.SetToolTip(this.mVmGroup, "This is the Milli Voltmeter\'s matrix.");
//
// milliVmGroup (6.4 in tab order)
//
this.milliVmGroup.Controls.Add(this.mVmOS);
this.milliVmGroup.Controls.Add(this.mVmOff);
this.milliVmGroup.Controls.Add(this.mVmIS);
this.milliVmGroup.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.milliVmGroup.ForeColor = System.Drawing.Color.RoyalBlue;
this.milliVmGroup.Location = new System.Drawing.Point(8, 63);
this.milliVmGroup.Name = "milliVmGroup";
this.milliVmGroup.Size = new System.Drawing.Size(152, 71);
this.milliVmGroup.TabIndex = 4;
this.milliVmGroup.TabStop = false;
this.milliVmGroup.Text = "Matrix";
//
// mVmOff (6.4.2 in tab order)
//
this.mVmOff.AutoSize = true;
this.mVmOff.Checked = true;
this.mVmOff.Font = new System.Drawing.Font("Verdana", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.mVmOff.Location = new System.Drawing.Point(5, 49);
this.mVmOff.Name = "mVmOff";
this.mVmOff.Size = new System.Drawing.Size(42, 17);
this.mVmOff.TabIndex = 2;
this.mVmOff.TabStop = true;
this.mVmOff.Text = "Off";
this.toolTip.SetToolTip(this.mVmOff, "Click to disconnect the Milli Voltmeter. \r\nDisconnects K29, K8, and K30. \r\nConnec" +
"ts K3 and K11. \r\n \r\nNote: Normaly checked.");
this.mVmOff.UseVisualStyleBackColor = true;
this.mVmOff.Click += new System.EventHandler(this.MVmOff_Click);
и снимок экрана этого раздела формы:
групповое поле mV Meter
Если это поможет, в точке останова, когда происходит ошибочный клик, переключатель является единственным элементом управления, нарисованным в форме.
Решение проблемы
В общем, вы должны полагаться на CheckedChange и использовать Click только тогда, когда произошел щелчок.
Но я отвечу на ваш вопрос:
Кто-нибудь знает, что еще может привести к автоматическому щелчку элемента управления при запуске?
Ваш RadioButton сфокусирован, как и ожидалось. Тогда возникновение события Click является ошибкой логики, существующей в OnEnter
методе RadioButton. Он пытается вызвать OnClick, когда вы входите в элемент управления с помощью клавиши со стрелкой, но не может сделать это правильно, например, вызывает событие Click, даже если фокус автоматически переместился на элемент управления без клавиши со стрелкой.
Вы можете отключить создание события Click при входе в элемент управления, переопределив OnEnter:
using System;
using System.Windows.Forms;
public class MyRadioButton: RadioButton
{
protected override void OnEnter(EventArgs e)
{
RaiseOnEnter(e);
}
private void RaiseOnEnter(EventArgs e)
{
var EventEvent = typeof(Control).GetField("EventEnter",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Static).GetValue(null);
EventHandler handler = (EventHandler)Events[EventEvent];
handler?.Invoke(this, e);
}
}
Примечание о.NET 5 и 6
Та же проблема даже в .NET 5 и 6 RadioButton; если вы хотите использовать описанный выше обходной путь для этих версий, убедитесь, что вы получили это s_enterEvent
поле.
Комментариев нет:
Отправить комментарий