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.
Some time after the form's Load event handler finishes, one specific radio button's Click event fires automatically. 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
Googling turned up this SE answer, but that doesn't quite match my situation. 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. 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).
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:
//
// 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
If it helps, at the breakpoint when the errant Click happens, the radio button is the only control drawn on the form.
CodePudding user response:
In general, you should rely on CheckedChange and use Click only when click has happened.
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. Then raising of Click event is fault of the logic which exists in RadioButton's OnEnter
method. 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.
You can disable raising Click event when you enter the control by overriding 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);
}
}
Note about .NET 5 and 6
Same problem even in .NET 5 and 6 RadioButton; if you want to use above workaround for those versions, make sure you get the s_enterEvent
field.