简体   繁体   English

RadioButton Click 事件在启动时错误地触发

[英]RadioButton Click event erroneously fires on startup

Edit: This is a different issue than the one covered in this proposed duplicate .编辑:这是一个与本提议副本中涵盖的问题不同的问题。 That question addresses a different problem, and none of the answers there apply to my situation.这个问题解决了一个不同的问题,那里的答案都不适用于我的情况。 My radio button is checked from the start, as it is supposed to be.我的单选按钮从一开始就被检查了,因为它应该是。 It (or rather a member of it's group) is set using a saved Property during the Load event handler.它(或者更确切地说是它的组的成员)是在加载事件处理程序期间使用保存的属性设置的。 Also, as stated below, my troublesome radio button is NOT the first in the tab order.另外,如下所述,我麻烦的单选按钮不是选项卡顺序中的第一个。

I just started experiencing a problem on a WinForms application that I've been tasked with refactoring.我刚开始在 WinForms 应用程序上遇到问题,我的任务是重构。

Some time after the form's Load event handler finishes, one specific radio button's Click event fires automatically.窗体的 Load 事件处理程序完成一段时间后,一个特定单选按钮的 Click 事件会自动触发。 I can't figure out why, and it's messing up the expected flow of the program.我不明白为什么,它打乱了程序的预期流程。

I've put a breakpoint at the start of the click handler and checked the call stack, but the troublesome call always comes from external code, the last two lines of which are RadioButton.OnEnter followed by Control.OnClick我在单击处理程序的开头放置了一个断点并检查了调用堆栈,但麻烦的调用总是来自外部代码,最后两行是 RadioButton.OnEnter,然后是 Control.OnClick

Googling turned up this SE answer , but that doesn't quite match my situation.谷歌搜索出现了这个 SE answer ,但这与我的情况不太相符。 The offending radio button is fairly late in the tab order, all controls are added in VS Designer rather than by code, and the Load handler sets Focus to a different control right before it finishes.有问题的单选按钮在选项卡顺序中相当靠后,所有控件都是在 VS 设计器中添加的,而不是通过代码添加的,加载处理程序在完成之前将焦点设置到另一个控件。 No reference to the radio button is encountered between the end of the Load handler and the erroneous Click (verified using way too many breakpoints).在 Load 处理程序的末尾和错误的 Click 之间没有遇到对单选按钮引用(使用太多断点进行验证)。

Does anyone have any idea what else might cause a control to be automatically clicked on startup?有谁知道还有什么可能导致在启动时自动单击控件?

Edit Here's the designer code for the radio button (mVmOff) and the nested groupboxes it is in:编辑这是单选按钮 (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);

and a screenshot of that section of the form: mV Meter group box以及表格该部分的屏幕截图: mV Meter 组合框

If it helps, at the breakpoint when the errant Click happens, the radio button is the only control drawn on the form.如果有帮助,在错误点击发生的断点处,单选按钮是唯一绘制在窗体上的控件。

In general, you should rely on CheckedChange and use Click only when click has happened.通常,您应该依赖 CheckedChange 并仅在发生点击时才使用 Click。

But I'll answer your question:但我会回答你的问题:

Does anyone have any idea what else might cause a control to be automatically clicked on startup?有谁知道还有什么可能导致在启动时自动单击控件?

Your RadioButton is focused as expected.您的 RadioButton 按预期聚焦。 Then raising of Click event is fault of the logic which exists in RadioButton's OnEnter method.然后引发 Click 事件是 RadioButton 的OnEnter方法中存在的逻辑错误。 It's trying to raise OnClick when you enter the control using arrow key, but it fails doing it in a right way, for example it raises Click event even if the focus has moved to the control automatically without an arrow key.当您使用箭头键输入控件时,它会尝试引发 OnClick,但它无法以正确的方式执行此操作,例如,即使焦点在没有箭头键的情况下自动移动到控件,它也会引发 Click 事件。

You can disable raising Click event when you enter the control by overriding OnEnter:您可以通过覆盖 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);
    }
}

Note about .NET 5 and 6关于 .NET 5 和 6 的注意事项

Same problem even in .NET 5 and 6 RadioButton ;即使在.NET 5 和 6 RadioButton中也有同样的问题; if you want to use above workaround for those versions, make sure you get the s_enterEvent field.如果您想对这些版本使用上述解决方法,请确保您获得s_enterEvent字段。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM