RadioButton Click 事件在启动时错误地触发
RadioButton Click event erroneously fires on startup
编辑: 这是一个与涵盖的问题不同的问题 in this proposed duplicate。该问题解决了一个不同的问题,none 的答案适用于我的情况。我的单选按钮从一开始就被选中,因为它是 supposed。它(或者更确切地说是它的组的成员)在 Load 事件处理程序中使用保存的 属性 设置。另外,如下所述,我麻烦的单选按钮不是 Tab 键顺序中的第一个。
我刚开始在 WinForms 应用程序上遇到问题,我的任务是重构。
在窗体的 Load 事件处理程序完成一段时间后,一个特定单选按钮的 Click 事件会自动触发。我不明白为什么,它打乱了程序的预期流程。
我在click handler的开头打了一个断点,查看了调用栈,但是麻烦的调用总是来自外部代码,最后两行是RadioButton.OnEnter后面是Control.OnClick
谷歌搜索出现 this SE answer,但这与我的情况不太相符。有问题的单选按钮在选项卡顺序中相当靠后,所有控件都是在 VS 设计器中添加的,而不是通过代码添加的,加载处理程序在完成之前将 Focus 设置为 different 控件。在 Load 处理程序的末尾和错误的 Click 之间没有遇到对单选按钮的引用(使用 way too many breakpoints 验证)。
有谁知道还有什么可能导致控件在启动时自动单击?
编辑
这是单选按钮 (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 group box
如果有帮助,在错误点击发生的断点处,单选按钮是唯一绘制在窗体上的控件。
一般情况下,您应该依赖 CheckedChange 并仅在发生点击时使用 Click。
但我会回答你的问题:
Does anyone have any idea what else might cause a control to be automatically clicked on startup?
您的 RadioButton 已按预期获得焦点。然后引发 Click 事件是 RadioButton 的 OnEnter
方法中存在的逻辑错误。当您使用箭头键输入控件时,它会尝试引发 OnClick,但它无法以正确的方式执行此操作,例如,即使焦点已在没有箭头键的情况下自动移动到控件,它也会引发 Click 事件。
您可以通过重写 OnEnter 来禁止在进入控件时引发 Click 事件:
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 and 6 RadioButton 中也有同样的问题;如果您想对这些版本使用上述解决方法,请确保您获得 s_enterEvent
字段。
编辑: 这是一个与涵盖的问题不同的问题 in this proposed duplicate。该问题解决了一个不同的问题,none 的答案适用于我的情况。我的单选按钮从一开始就被选中,因为它是 supposed。它(或者更确切地说是它的组的成员)在 Load 事件处理程序中使用保存的 属性 设置。另外,如下所述,我麻烦的单选按钮不是 Tab 键顺序中的第一个。
我刚开始在 WinForms 应用程序上遇到问题,我的任务是重构。
在窗体的 Load 事件处理程序完成一段时间后,一个特定单选按钮的 Click 事件会自动触发。我不明白为什么,它打乱了程序的预期流程。
我在click handler的开头打了一个断点,查看了调用栈,但是麻烦的调用总是来自外部代码,最后两行是RadioButton.OnEnter后面是Control.OnClick
谷歌搜索出现 this SE answer,但这与我的情况不太相符。有问题的单选按钮在选项卡顺序中相当靠后,所有控件都是在 VS 设计器中添加的,而不是通过代码添加的,加载处理程序在完成之前将 Focus 设置为 different 控件。在 Load 处理程序的末尾和错误的 Click 之间没有遇到对单选按钮的引用(使用 way too many breakpoints 验证)。
有谁知道还有什么可能导致控件在启动时自动单击?
编辑 这是单选按钮 (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 group box
如果有帮助,在错误点击发生的断点处,单选按钮是唯一绘制在窗体上的控件。
一般情况下,您应该依赖 CheckedChange 并仅在发生点击时使用 Click。
但我会回答你的问题:
Does anyone have any idea what else might cause a control to be automatically clicked on startup?
您的 RadioButton 已按预期获得焦点。然后引发 Click 事件是 RadioButton 的 OnEnter
方法中存在的逻辑错误。当您使用箭头键输入控件时,它会尝试引发 OnClick,但它无法以正确的方式执行此操作,例如,即使焦点已在没有箭头键的情况下自动移动到控件,它也会引发 Click 事件。
您可以通过重写 OnEnter 来禁止在进入控件时引发 Click 事件:
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 and 6 RadioButton 中也有同样的问题;如果您想对这些版本使用上述解决方法,请确保您获得 s_enterEvent
字段。