17

我看到复选框有一个 CheckedChanged 事件。是否可以通过编程方式或用户实际检查复选框来判断它是否已更改?

我有一个大网格,用户可以在其中输入过滤器,或者使用复选框来提供一种提供常用过滤参数的“快速过滤器”。然后说他们去通过文本框修改过滤器,我正在检查我是否应该以编程方式(取消)检查 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;
    }

通过一些非常简单的测试,这似乎就像我想要的那样工作。但我担心存在某种“无限循环”情况,其中 ColumnFilterChanged 事件会因为在 CheckedChanged 事件发生时调用 UpdateFilter 方法而触发,这反过来可能导致 CheckedChange 再次发生,因为 ColumnFilterChanged 操纵复选框。

4

3 回答 3

13

用于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的设置器中引发。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;
于 2013-10-21T17:22:22.640 回答
10

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

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;
}
于 2013-10-21T17:21:06.180 回答
8

一般来说,您可以使用Click 事件CheckBoxName_Click ,该事件仅在用户单击复选框时调用(而不是当您从代码中设置复选框选中属性时),正如事件名称所暗示的那样。

于 2017-04-03T11:30:49.340 回答