WPF:如何防止 ComboBox 作为 ToggleButton 触发 CheckBox.Checked 事件?
我的窗口中有很多控件,包括复选框和组合框。我想跟踪 CheckBox.IsChecked 事件,因此我在 Windows 级别定义了一个事件处理程序为
<Grid CheckBox.Checked="OnModified" CheckBox.Unchecked="OnModified">
问题是,在鼠标单击某个项目后,ComboBox 也会立即触发相同的事件。我认为我的事件处理程序应该只捕获 CheckBox 的 Checked 事件,而不是 ToggleButton 的事件。我错过了什么吗?
编辑: 正如我在下面指出的,我认为它会以这种方式工作,因为我阅读了 Matthew MacDonald 的书“Pro WPF in C# 2010”。 在第164页,他首先给出了这个示例代码:
<StackPanel Button.Click="DoSomething" Margin="5">
<Button Name="cmd1">Command 1</Button>
<Button Name="cmd2">Command 2</Button>
<Button Name="cmd3">Command 3</Button>
...
</StackPanel>
然后,他特别指出:
注意Click事件实际上是 在 ButtonBase 类中定义并且 由 Button 类继承。如果你 将事件处理程序附加到 ButtonBase.Click,该事件处理程序 将在任何时候使用 单击 ButtonBase 派生的控件 (包括按钮、单选按钮、 和复选框类)。如果您附加 Button.Click 的事件处理程序, 它仅用于 Button 对象。
现在,是我误解了他,还是他的注释有误?
I have a lots of controls in a Window including checkboxes and comboboxes. I want to track CheckBox.IsChecked event, so I defined an event handler in Windows level as
<Grid CheckBox.Checked="OnModified" CheckBox.Unchecked="OnModified">
The problem is that the same event is also fired by ComboBox right after mouse clicking an item. I thought my event handler should only capture CheckBox's Checked event, not ToggleButton's. Did I miss anything?
EDIT:
As I pointed out below, I thought it would work this way because I read Matthew MacDonald's book "Pro WPF in C# 2010". On page 164, he gave this example code first:
<StackPanel Button.Click="DoSomething" Margin="5">
<Button Name="cmd1">Command 1</Button>
<Button Name="cmd2">Command 2</Button>
<Button Name="cmd3">Command 3</Button>
...
</StackPanel>
Then, he specially noted:
Note The Click event is actually
defined in the ButtonBase class and
inherited by the Button class. If you
attach an event handler to
ButtonBase.Click, that event handler
will be used when any
ButtonBase-derived control is clicked
(including the Button, RadioButton,
and CheckBox classes). If you attach
an event handler to Button.Click,
it’s only used for Button objects.
Now, did I misunderstand him, or is his note wrong?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
实际上并没有单独的
CheckBox.Checked
事件。如果您查看此页面:并找到
Checked
事件,您将看到它是从ToggleButton
继承的,因此ToggleButton.Checked
和CheckBox.Checked
是同一事件的两个不同名称。由于您正在订阅“通配符”事件,因此在事件处理程序中,您可以检查发件人或来源以查看您是否感兴趣。
编辑:
解决有关以下问题的后续问题:书中的引用,我认为引用至少具有误导性。这是一个反例,显示
CheckBox
对Button
事件做出反应,即使CheckBox
不是从Button
派生的:当然没有
Button.Click
事件,只有ButtonBase.Click
事件,但这就是引用的关键。如果引用字面意思是正确的,则要么不允许使用此语法,要么不会触发事件,这两者都不是正确的。There is not actually a separate
CheckBox.Checked
event. If you look at this page:and find the
Checked
event you will see that it is inherited fromToggleButton
soToggleButton.Checked
andCheckBox.Checked
are two different names for the same event.Since you are subscribing to a "wildcard" event, in the event handler you can check the sender or source to see you it is one you are interested in.
Edit:
To address your follow-on question regarding the book quote, I think the quote is at least misleading. Here is a counter-example that shows a
CheckBox
reacting toButton
event even thoughCheckBox
is not derived fromButton
:Of course there is no
Button.Click
event, only aButtonBase.Click
event, but that is the crux of the quote. If the quote were literally true, either this syntax would not be permitted or the event wouldn't fire, neither of which is true.这是因为您正在网格上设置事件,因此网格包含的任何具有
Checkbox.Checked
路由事件的子项都将响应该事件。在您的情况下,ComboboxItem
使用相同的路由事件(我确信其他控件也可能重用它),处理此问题的最简单方法是向您的处理程序添加一个测试,像这样的东西:
its because you are setting the event on the grid, so any children contained by the grid that have a
Checkbox.Checked
routed event will respond to the event. In your case, it happens that theComboboxItem
uses the same routed event (and I am sure other controls probably reuse it as well)the easiest way to handle this would be to add a test to your handler, something like this:
发生这种情况是因为两个事件都会在元素树中冒泡,并且都到达您的处理程序(
CheckBox
继承ToggleButton
,因此CheckBox.Checked
和ToggleButton.Checked 实际上是相同的事件)。你无法阻止这一点。您可以做的是检查事件是否由
CheckBox
引发。可以这样做:This happens because both events get bubbled up the elements tree and both reach your handler (
CheckBox
inheritsToggleButton
, henceCheckBox.Checked
andToggleButton.Checked
are in fact the same events). You cannot prevent this. What you can do instead is to check whether the event was raised by aCheckBox
. It can be done like this:我曾经通过检查它是否获得焦点来阻止 Checkbox.Checked 事件。因为当它从绑定中触发时,它不会聚焦,但是当您单击它时,它就会聚焦。
希望这有帮助。
布莱里姆。
I used to prevent Checkbox.Checked event by checking if it is focused or not. Because when it fires from binding it is not Focused, but when you click on it than it is focused.
Hope this helps.
Blerim.
我是“Pro WPF in C# 2010”的作者,我可以确认注释框中的文本属于“我在吸烟什么?”类别。根据您在标记中引用的方式,Click 事件之间没有区别。
马修
I'm the author of "Pro WPF in C# 2010" and I can confirm that the text from the Note box falls under the "what was I smoking?" category. There is no distinction between the Click event based on how you refer to it in your markup.
Matthew