WPF:如何防止 ComboBox 作为 ToggleButton 触发 CheckBox.Checked 事件?

发布于 2024-11-04 13:25:28 字数 1013 浏览 1 评论 0原文

我的窗口中有很多控件,包括复选框和组合框。我想跟踪 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

奶茶白久 2024-11-11 13:25:28

实际上并没有单独的 CheckBox.Checked 事件。如果您查看此页面:

并找到 Checked 事件,您将看到它是从 ToggleButton 继承的,因此 ToggleButton.CheckedCheckBox.Checked是同一事件的两个不同名称。

由于您正在订阅“通配符”事件,因此在事件处理程序中,您可以检查发件人或来源以查看您是否感兴趣。

编辑:

解决有关以下问题的后续问题:书中的引用,我认为引用至少具有误导性。这是一个反例,显示 CheckBoxButton 事件做出反应,即使 CheckBox 不是从 Button 派生的:

<CheckBox Button.Click="CheckBox_Click"/>

当然没有 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 from ToggleButton so ToggleButton.Checked and CheckBox.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 to Button event even though CheckBox is not derived from Button:

<CheckBox Button.Click="CheckBox_Click"/>

Of course there is no Button.Click event, only a ButtonBase.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.

鹿! 2024-11-11 13:25:28

这是因为您正在网格上设置事件,因此网格包含的任何具有 Checkbox.Checked 路由事件的子项都将响应该事件。在您的情况下,ComboboxItem 使用相同的路由事件(我确信其他控件也可能重用它),

处理此问题的最简单方法是向您的处理程序添加一个测试,像这样的东西:

private void OnModified(object sender, EventArgs args)
{
    if ( sender is CheckBox )
    {
        CheckBox ckBox = sender as CheckBox;
        // do stuff with ckBox
    }
}

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 the ComboboxItem 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:

private void OnModified(object sender, EventArgs args)
{
    if ( sender is CheckBox )
    {
        CheckBox ckBox = sender as CheckBox;
        // do stuff with ckBox
    }
}
夜灵血窟げ 2024-11-11 13:25:28

发生这种情况是因为两个事件都会在元素树中冒泡,并且都到达您的处理程序(CheckBox 继承 ToggleButton,因此 CheckBox.CheckedToggleButton.Checked 实际上是相同的事件)。你无法阻止这一点。您可以做的是检查事件是否由 CheckBox 引发。可以这样做:

private void OnModified(object sender, RoutedEventArgs e)
{
    // Filter the event by its source
    if (e.Source.GetType() != typeof(CheckBox))
        return;

    // Your handling code         
}

This happens because both events get bubbled up the elements tree and both reach your handler (CheckBox inherits ToggleButton, hence CheckBox.Checked and ToggleButton.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 a CheckBox. It can be done like this:

private void OnModified(object sender, RoutedEventArgs e)
{
    // Filter the event by its source
    if (e.Source.GetType() != typeof(CheckBox))
        return;

    // Your handling code         
}
赠我空喜 2024-11-11 13:25:28

我曾经通过检查它是否获得焦点来阻止 Checkbox.Checked 事件。因为当它从绑定中触发时,它不会聚焦,但是当您单击它时,它就会聚焦。

 if(cbo.IsFocused){ // code here }

希望这有帮助。
布莱里姆。

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.

 if(cbo.IsFocused){ // code here }

Hope this helps.
Blerim.

匿名。 2024-11-11 13:25:28

我是“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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文