区分用户更改Checkbox.Checked值还是以编程方式更改 [英] Differentiate between a user changing the Checkbox.Checked value, or it programmatically changing

查看:64
本文介绍了区分用户更改Checkbox.Checked值还是以编程方式更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到复选框具有CheckedChanged事件.是否可以判断它是通过编程方式更改还是由用户实际选中复选框?

I see that Checkboxes have a CheckedChanged event. is it possible to tell whether it was changed programmatically, or by the user actually checking the checkbox?

我有一个很大的网格,用户可以在其中键入过滤器,也可以使用复选框来提供一种提供常用过滤参数的快速过滤器".然后说他们去修改文本框中的过滤器,我正在检查是否应该以编程方式(取消)检查CheckBox控件,以便它可以在文本框中反映过滤器.

I've got a large grid where the user can type in a filter, or use checkboxes for a sort of "Quick filter" that offers common filtering parameters. Then say they go and modify the filter through the textbox, I was checking whether or not I should programmatically (un)check the CheckBox controls so that it reflects the filter in the textbox.

    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.

With some very light testing, this seems to work just as I want it to. But I'm afraid that there's some sort of 'infinite loop' case where the ColumnFilterChanged event will fire because of the UpdateFilter method being called when the CheckedChanged event happens, which could in turn cause CheckedChange to happen again since the ColumnFilterChanged manipulates the Checkboxes.

推荐答案

为此目的使用 flag 是可以的:

Using flag for this purpose is OK:

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 更为简洁,并且代码也具有连贯性:

UPDATE

Using flag is the best way (the most concise and convenient) I think. However, after some searching on the internal implementation of CheckBox.cs, I've found that the internal field checkState is used. the Checked property is designed just for convenience. The CheckedChanged event is raised in the setter of the CheckState property. So by modifying the checkState field, we bypass the CheckedChanged event raiser. Because the field checkState is not public, we have to use Reflection to change its value. That's why this code is a little lengthy compared to using flag. This is the code for you, note that this is just a reference to open wide the knowledge on this problem, as I said using flag is much more concise and the code is also coherent:

//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;

这篇关于区分用户更改Checkbox.Checked值还是以编程方式更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆