views:

93

answers:

1

Hello,

I have two controls A and B. Control B is placed over A. When B is clicked only it's clicked event is fired, however I need the click event of A to fire too. Can this somehow be realized using routed events?

Here's a screenshot of the controls:

alt text

Of course this case is just a reduced example, I'm looking for a general way to raise events on all controls below the mouse cursor / at one location. Hoewever, a concrete solution to this problem would help me too! Thank you very much for any hint!

+1  A: 

This can happen if the event handler of the inner control sets the e.Handled property to true. This would prevent the routed event from bubbling any further. But I just checked and I do not see that behavior in WPF 4.

If e.Handled is preventing your event, what you can do however is use the UIElement.AddHandler overload that takes a boolean handledEventsToo parameter to hook up your click event. This has to be done in code, not markup. Then you should receive the Click event in the outer control and the e.Handled property will already be set to true.

The following code does set the background of both buttons when I click the inner button.

<Grid>
    <Button VerticalAlignment="Center" HorizontalAlignment="Center" Click="Click1">
        <Button Width="100" Height="25" Margin="20" Click="Click2" />
    </Button>
</Grid>

Code Behind

private void Click1( object sender, RoutedEventArgs e )
{
    ( (Button)sender ).Background = new SolidColorBrush( Colors.Blue );
}

private void Click2( object sender, RoutedEventArgs e )
{
    ( (Button)sender ).Background = new SolidColorBrush( Colors.Red );
    //e.Handled = true; // uncomment to stop bubbling
}
Josh Einstein
Worth noting that your solution *won't* make "the click event of `A` [...] fire too" as per the OP - though a handler for `Button.Click` registered on `ButtonA` *will* also catch the event. It's a subtle but important difference!
Dan Puzey
Hello Josh, thank you for your reply. Took me a while to find out why yours works: You placed the second button *inside* and not *above* the other one. Dans way is a possiblity too, I'm just wondering if there's a more comfortable way. Something like automatically passing through events like it's done when IsHitTestVisible is set to false, however still notifying the control where IsHitTestVisible is false .. ):
stefan.at.wpf
@stefan - You can add a MouseLeftButtonDown handler to the root Window object using the handledEventsToo parameter then use VisualTreeHelper.HitTest to find out which elements intersect the point that was clicked. See http://msdn.microsoft.com/en-us/library/ms752097.aspx#using_a_hit_test_result_callback
Josh Einstein
Thank you Josh, also an interesting idea! Marked as answer.
stefan.at.wpf
Stefan, I too am looking for a way to set IsHitTestVisible to False but still be notified of certain mouse events: http://stackoverflow.com/questions/3893809/wpf-ignore-mouse-clicks-on-overlay-adorner-but-handle-mouseenter-event. What did you end up doing? I'm really not comfortable messing with hit testing code since in my case the controls underneath are dynamically generated. I'm sure it would work but seems like the wrong solution to me.
skypecakes