6

For some reason, child Expanders (placed in a StackPanel inside of another Expander), when collapsed or expanded, cause the parent Expander to raise its Expanded or Collapsed events.

Anyone know why this is or how I can change it? I'm only interested in the parent's events.

Here is some test XAML:

    <Expander Header="Outer" Expanded="Expander_Expanded" Collapsed="Expander_Collapsed">
        <StackPanel>
            <Expander Header="Inner1">
                <Canvas Height="100" Width="100" Background="Blue" />
            </Expander>
            <Expander Header="Inner2">
                <Canvas Height="100" Width="100" Background="Red" />
            </Expander>
        </StackPanel>
    </Expander>

and here is the code-behind:

    private void Expander_Expanded(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("expanded");
    }

    private void Expander_Collapsed(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("collapsed");
    }

When you run this, if you expand the parent, you get an "expanded" messagebox, as you'd expect. But when you then expand one of the children, you get the messagebox again.

The documentation for the Expanded event says:

The Expanded event occurs when the IsExpanded property changes from false to true

But clearly the IsExpanded property isn't changing on the parent Expander.

Why is this happening, any ideas?

H.B.
  • 166,899
  • 29
  • 327
  • 400
Tim
  • 14,999
  • 1
  • 45
  • 68

1 Answers1

12

Those events are routed and bubble up in the tree, if you want to prevent the parents from handling the event and thus reacting to it, set e.Handled to true in the child expander's event handler.

Edit: Instead of preventing the event from being raised you also could just restrict the code-execution in the handler to the case when the actual expander where the handler is attached raised the event. You can do this by wrapping everything in an if-block which executes if sender == e.OriginalSource.


(Woo, 10k...)

H.B.
  • 166,899
  • 29
  • 327
  • 400
  • Ah ok. I didn't realize that type of event would get Routed that way. Makes sense for mouse/keyboard interaction when it actually does impact the parent as well... but expanded seems an odd choice to be routed that way. Thanks for the response, H.B. – Tim May 18 '11 at 15:05
  • Indeed, i once programatically created a tree made up of expanders and the children just would not expand as expected due to this. – H.B. May 18 '11 at 15:06
  • Haha. I'm sure that was frustrating (as was this). Congrats on the 10k. I'm trying to work my way there! – Tim May 18 '11 at 15:07
  • 1
    @ Haris Hasan - make sure you're setting `e.Handled = true` in the child expander's event, not in the parent expander's event. – Tim May 18 '11 at 15:11
  • To be clear, just because it's a routed event doesn't mean it bubbles up the visual tree. Bubbling is one of three routing stratagies, which also include Direct (more like CLR events) and Tunnel (routes down the visual tree). – CodeNaked May 18 '11 at 15:56
  • @H.B. - Oh, and congrats! :-) – CodeNaked May 18 '11 at 15:56
  • @CodeNaked: Thanks! You are of course right and i am aware of the different strategies, i removed the implied inference `RoutedEvent => Bubbling`, you'd be welcome to directly edit my answers yourself if you see such inaccuracies. – H.B. May 18 '11 at 16:09
  • @Markus Hütter: A *Danke* to you as well :D – H.B. May 18 '11 at 20:05