区分用户更改Checkbox.Checked值,或以编程方式更改

时间:2013-10-21 17:17:36

标签: c# winforms checkbox

我看到Checkbox有一个CheckedChanged事件。是否可以判断它是以编程方式更改,还是由用户实际选中复选框?

我有一个大网格,用户可以输入过滤器,或使用复选框进行某种"快速过滤"提供常见的过滤参数。然后说他们去通过文本框修改过滤器,我正在检查是否应该以编程方式(un)检查CheckBox控件,以便它反映文本框中的过滤器。

    private void genericCheckbox_CheckedChanged(object sender, EventArgs e)
    {
        UpdateFilter();
    }

    private void UpdateFilter()
    {
        if (gdcSVNDefaultView.RowCount == 0)
            return;

        gdcSVNDefaultView.ActiveFilterString = BuildTableFilter();
        gdcSVNDefaultView.BestFitColumns();
    }

    private void gdcSVNDefaultView_ColumnFilterChanged(object sender, EventArgs e)
    {
        lblTotalFileCount.Text = gdcSVNDefaultView.RowCount.ToString();

        if (gdcSVNDefaultView.ActiveFilterString.Contains("Normal"))
            cheNormalFiles.Checked = true;
        else
            cheNormalFiles.Checked = false;

        if (gdcSVNDefaultView.ActiveFilterString.Contains("bin") || 
            gdcSVNDefaultView.ActiveFilterString.Contains("obj"))
            cheBinObjFolders.Checked = true;
        else
            cheBinObjFolders.Checked = false;
    }

通过一些非常轻微的测试,这似乎就像我想要的那样工作。但是,我担心会出现某种“无限循环”。由于在CheckedChanged事件发生时调用UpdateFilter方法而导致ColumnFilterChanged事件将触发的情况,这可能会导致CheckedChange再次发生,因为ColumnFilterChanged操作了Checkboxes。

3 个答案:

答案 0 :(得分:8)

我可能会分离并重新连接处理程序,例如

private void gdcSVNDefaultView_ColumnFilterChanged(object sender, EventArgs e)
{
    cheNormalFiles.CheckedChanged -= genericCheckbox_CheckedChanged;
    cheBinObjFolders.CheckedChanged -= genericCheckbox_CheckedChanged;

    // do stuff...

    cheNormalFiles.CheckedChanged += genericCheckbox_CheckedChanged;
    cheBinObjFolders.CheckedChanged += genericCheckbox_CheckedChanged;
}

答案 1 :(得分:8)

使用flag就可以了:

bool suppressCheckedChanged;
private void gdcSVNDefaultView_ColumnFilterChanged(object sender, EventArgs e)
{
   suppressCheckedChanged = true;
   //.... your own code
   //....
   suppressCheckedChanged = false;
}
private void genericCheckbox_CheckedChanged(object sender, EventArgs e)
{
    if(suppressCheckedChanged) return;
    UpdateFilter();
}

更新

我认为使用flag是最好的方法(最简洁方便)。但是,在对CheckBox.cs 的内部实现进行了一些搜索之后,我发现使用了内部字段 checkState Checked属性的设计只是为了方便起见。在CheckedChanged属性的setter中引发CheckState事件。因此,通过修改checkState字段,我们会绕过CheckedChanged事件加注者。由于字段checkState不公开,我们必须使用Reflection来更改其值。这就是为什么与使用flag相比,这段代码有点冗长。 这是你的代码,请注意,这只是一个参考,以打开这个问题的知识,正如我所说的使用flag更简洁,代码也是连贯的:

//Use this extension method for convenience
public static class CheckBoxExtension {
  public static void SetChecked(this CheckBox chBox, bool check){
    typeof(CheckBox).GetField("checkState", BindingFlags.NonPublic |
                                            BindingFlags.Instance)
                    .SetValue(chBox, check ? CheckState.Checked : 
                                             CheckState.Unchecked);
    chBox.Invalidate();
  }
}
//then you can use the SetChecked method like this:
checkBox1.SetChecked(true);//instead of checkBox1.Checked = true;
checkBox1.SetChecked(false);//instead of checkBox1.Checked = false;

答案 2 :(得分:6)

一般情况下,您可以使用 Click事件 CheckBoxName_Click,仅当用户单击复选框时(而不是在您从代码中设置复选框选中属性时)才会调用该事件,如事件名称所示。