我有一个复选框,我订阅了CheckedChanged事件。处理程序在那里执行一些操作。我以编程方式检查并取消选中该复选框(例如:chkbx_Name.Checked = true
),并且CheckedChanged事件被触发。
我希望只有在手动选中或取消选中时才会触发此事件。当我以编程方式检查/取消选中时,有没有办法避免触发此事件?
答案 0 :(得分:13)
在设置之前取消订阅该事件:
check1.CheckChanged -= check1_CheckChanged;
然后您可以以编程方式设置值,而不会勾选其CheckChanged事件:
check1.Checked = true;
然后重新订阅:
check1.CheckChanged += check1_CheckChanged;
[编辑:2012年3月29日]
Tanvi方法的问题是您需要捕获手动检查或取消选中的所有来源。并不是说太多了(只能通过鼠标点击和用户按空格键),但你必须考虑从MouseClick和KeyUp调用重构事件(检测空格键)
对于CheckBox(任何控件)来说,对于用户输入源(键盘,鼠标等)是不可知的更为简洁,所以为此,我将使CheckBox的编程设置真正具有编程性。例如,您可以将属性的编程设置包装到扩展方法:
static class Helper
{
public static void SetCheckProgrammatically(
this CheckBox c,
EventHandler subscribedEvent, bool b)
{
c.CheckedChanged -= subscribedEvent; // unsubscribe
c.Checked = b;
c.CheckedChanged += subscribedEvent; // subscribe
}
}
使用这种方法,您的代码可以通过一个事件(即通过CheckChanged)对用户的鼠标输入和键盘输入做出整齐的响应。没有重复的代码,无需订阅多个事件(例如键盘,通过按空格键检查/取消选中CheckBox)
答案 1 :(得分:5)
没有。无论这是由您的代码,控件自己的代码还是数据绑定完成,属性值更改时都会触发这些属性更改事件。它通常都是相同的代码路径。
但是,如果事件处理程序与更改属性值的代码位于同一个类中,则可以执行的操作是在类中引入一个私有布尔字段,用于指示当前属性是否更改由您的代码或用户触发。更改后,您只需重置它。然后,事件处理程序将查看该字段并确定它是否应该执行任何操作:
class Foo : Form {
private bool checkedProgrammatically = false;
void someMethod() {
// ...
checkedProgrammatically = true;
checkBox1.Checked = true;
checkedProgrammatically = false;
// ...
}
private void checkBox1_CheckChanged(object sender, EventArgs e) {
if (checkedProgrammatically) return;
// ...
}
}
答案 2 :(得分:1)
对不起我不能仅仅评论迈克尔·布恩的答案,因为我在这里是新人(没有名声),但是对于它的价值我非常喜欢他对约翰内斯·罗塞尔的解决方案有几个原因。
1)对于我来说,checkedProgrammatically变量有点太接近全局了。没有什么可以阻止另一种方法意外地将其设置为true,导致所有事件停止。
2)根据您正在处理的事件数量,您可能会得到很多变量。修改错误的内容很容易,结果很难调试。
3)当您取消订阅然后重新订阅时,您正在做的事情更加明显。所有逻辑都在那里,您不需要根据特定条件更改事件处理程序以提前退出。
我已广泛使用这两种方法,从长远来看,我觉得迈克尔更容易。
答案 3 :(得分:1)
您可以使用 MouseClick 事件,并在该检查中选中复选框的选中状态。 这样它就不会以编程方式触发,只有在用户手动选中或取消选中复选框时才会调用它。
答案 4 :(得分:0)
您可以在更改值programiticaly之前设置布尔变量,并检查比在checkedchanged事件中重置该变量