WPF: Как предотвратить запуск события CheckBox.Checked для ComboBox как ToggleButton? - PullRequest
4 голосов
/ 01 мая 2011

У меня есть много элементов управления в окне, включая флажки и комбинированные списки.Я хочу отслеживать событие CheckBox.IsChecked, поэтому я определил обработчик событий на уровне Windows как

<Grid CheckBox.Checked="OnModified" CheckBox.Unchecked="OnModified">

Проблема в том, что это же событие также вызывается ComboBox сразу после щелчка мышью по элементу.Я думал, что мой обработчик события должен захватывать только событие CheckBox Checked, а не ToggleButton.Я что-то пропустил?

РЕДАКТИРОВАТЬ: Как я указал ниже, я думал, что это будет работать так, потому что я прочитал книгу Мэтью Макдональда" Pro WPF в 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, RadioButton и CheckBox).Если вы присоединяете обработчик событий к Button.Click, он используется только для объектов Button.

Теперь, я его неправильно понял или его примечание неверно?

Ответы [ 4 ]

2 голосов
/ 01 мая 2011

На самом деле отдельного события CheckBox.Checked не существует.Если вы посмотрите на эту страницу:

и найдете событие Checked, вы увидите, что оно унаследовано от ToggleButton so ToggleButton.Checked и CheckBox.Checked - это два разных имени одного и того же события.

Поскольку вы подписываетесь на событие с подстановочными знаками, в обработчике событий вы можете проверить отправителя или источник, чтобы увидеть его.это тот, который вас интересует.

Редактировать:

Чтобы ответить на следующий вопрос, касающийся цитаты из книги, я думаю, что цитата, по крайней мере, вводит в заблуждение.Вот контрпример, который показывает, что CheckBox реагирует на событие Button, хотя CheckBox не является производным от Button:

<CheckBox Button.Click="CheckBox_Click"/>

Конечно, нет события Button.Click,только событие ButtonBase.Click, но это суть цитаты.Если бы цитата была буквально истинной, либо этот синтаксис был бы недопустим, либо событие не сработало бы, ни то, ни другое не является правдой.

1 голос
/ 01 мая 2011

Это происходит потому, что оба события запутываются в дереве элементов и оба достигают вашего обработчика (CheckBox наследует ToggleButton, следовательно, CheckBox.Checked и ToggleButton.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         
}
1 голос
/ 01 мая 2011

потому что вы устанавливаете событие в сетке, поэтому любые дочерние элементы, содержащиеся в сетке, имеющие перенаправленное событие Checkbox.Checked, будут реагировать на событие.В вашем случае, случается, что ComboboxItem использует одно и то же перенаправленное событие (и я уверен, что другие элементы управления, вероятно, также используют его повторно)

самый простой способ справиться с этим - добавить тест в ваш обработчикпримерно так:

private void OnModified(object sender, EventArgs args)
{
    if ( sender is CheckBox )
    {
        CheckBox ckBox = sender as CheckBox;
        // do stuff with ckBox
    }
}
0 голосов
/ 04 мая 2011

Я являюсь автором "Pro WPF в C # 2010" и могу подтвердить, что текст из поля "Примечание" подпадает под "что я курил?" категория. Нет никакого различия между событием Click в зависимости от того, как вы ссылаетесь на него в разметке.

Мэтью

...