单选按钮的选中状态更改事件触发两次。

41
请仔细阅读我的问题,它不是重复的。
我在Windows表单上有三个单选按钮,所有这些按钮都关联了一个共同的“CheckedChanged”事件。当我点击其中任何一个单选按钮时,它会触发两次“CheckedChanged”事件。
以下是我的代码:
private void radioButtons_CheckedChanged(object sender, EventArgs e)
{
    //My Code
}

我插入了断点,该事件中的整个代码会迭代两次。 请告诉我为什么会这样?


1
您的问题已经有答案,请参见 https://dev59.com/rV3Ua4cB1Zd3GeqP8gNq。 - HatSoft
3
似乎您所链接的答案与此问题无关。 - Michael Parker
8个回答

82

正如其他回答所说,事件会被触发两次,因为在组中选中一个RadioButton时,另一个将被取消选中 - 因此,CheckedChanged事件将触发两次。

要仅对刚选中的RadioButton执行此事件中的任何操作,您可以查看发送者对象,并执行类似以下操作的操作:

void radioButtons_CheckedChanged(object sender, EventArgs e)
{
    RadioButton rb = sender as RadioButton;
    if (rb != null)
    {
        if (rb.Checked)
        {
            // Only one radio button will be checked
            Console.WriteLine("Changed: " + rb.Name);
        }
    }
}

2
你不觉得 'if (rb != null)' 是不必要的吗? - Muhammad Ali Dildar
4
这里避免了任何空引用异常的可能性 - 当然,由于您连接所有事件,所以您可以非常确定此事件处理程序仅附加到单选按钮,但是“最佳实践”是检查强制转换是否起作用。另一方面 - 从某种角度来看,如果您在错误地附加事件处理程序时抛出异常,可能更可取,这样您就可以修复代码。 - David Hall

6
为了避免这种情况,只需检查 radioButton 是否被选中即可。
例如:
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
    if (radioButton1.Checked)
        //your code
}

5

每当Checked属性发生变化时,都会引发CheckedChanged事件。如果您选择一个单选按钮,那么之前选中的单选按钮将被取消选中(触发CheckedChanged事件),然后新的单选按钮将被选中(触发CheckedChanged事件)。


2

当单选按钮从选中状态变为未选中状态时,它会触发一次;当单选按钮从未选中状态变为选中状态时,它也会触发一次(即任何选中状态的更改都会触发事件)。


0
你可以为每个单选按钮设置AutoCheck属性为true,然后捕获Click事件而不是CheckChanged事件。这将确保只触发一个事件,并且处理程序中的逻辑可以将发送者转换为RadioButton类型(如果需要处理点击)。如果处理程序逻辑很简单,则通常可以避免转换。以下是一个处理三个控件rbTextNumeric、rbTextFixed和rbTextFromFile的示例:
        private void rbText_Click(object sender, EventArgs e)
    {
       flowLayoutPanelTextNumeric.Enabled = rbTextNumeric.Checked;
       txtBoxTextFixed.Enabled = rbTextFixed.Checked;
       flowLayoutPanelTextFromFile.Enabled = rbTextFromFile.Checked;
    }

这似乎适用于Windows Forms,但不适用于WebForms。 - codeMonkey

0
{
    public partial class Form3 : Form
    {
        public Form3()
        {
            InitializeComponent();
        }
        int click = 0;
        private void radioButton1_Click(object sender, EventArgs e)
        {
            click++;
            if (click %2==1)
            {
                radioButton1.Checked = true;
            }
            if (click %2==0)
            {
                radioButton1.Checked = false;
            }
            if (radioButton1.Checked==true)
            {
                label1.Text = "Cheked";
            }
            if (radioButton1.Checked==false)
            {
                label1.Text = "Uncheked";
            }
        }

    }
}

@davidkonrad 真正的代码永远不需要任何解释!噢! - user4624979

0

当一系列的RadioButton点击连续发生时,就会出现这种重复检查的问题。我曾经遇到过同样的问题。最后一次点击会产生两个结果。为了克服这个问题,我在最后进行了一个虚拟点击。这样双击就停止了。可以尝试这种方法。 Venkatraman


0
其他答案是正确的,但忽略了潜在问题的原因。当单选按钮被选中时,第一个发送的事件是从未选中的项目更改,但是如果您通过其控件名称检查其状态,则仍将看到其旧的选中状态,因为表单尚未更新。要查看其真实状态,您需要转换发送方对象。这使您能够执行与正在取消选择的条件相关的任何操作(如果需要)。
在下面的不常见情况下,多个单选按钮被发送到同一处理程序事件。仅检查已选中的发送方的状态在这里不起作用,因为我们需要根据按下哪个单选按钮执行不同的操作。因此,首先我们忽略刚刚取消选择的任何发送方,然后通过控件名称识别已选中的发送方以处理正确的操作。
private void ModeChangedExample(object sender, EventArgs e)
{
    // multiple radio buttons come here
    // We only want to process the checked item.
    // if you need to something based on the item which was just unchecked don't use this technique. 
    // The state of the sender has not been updated yet in the form.
    // so checking against rdo_A check state will still show it as checked even if it has just been unchecked
    // only the sender variable is up to date at this point.
        
    // To prevent processing the item which has just been uncheked
    RadioButton RD = sender as RadioButton;
    if (RD.Checked == false) return;

    if (rdo_A.Name == RD.Name)
    {
        //Do stuff
    }

    if (rdo_B..Name == RD.Name)
    {
        // Do other stuff
    }

    if (rdo_C.Name == RD.Name)
    {
        // Do something else
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接