Page view counter

Beta 2 Event Bubbling

There are many great changes in Beta 2, and some are designed to make Silverlight more like WPF. One side effect of this is that event bubbling has changed just a bit and that bit breaks some of the examples I love to use.

In Beta 1, the distinction was that all the controls handled their own click events but the more primitive events such as many of the mouse events were allowed to bubble. This allowed for interesting if not terribly useful demonstrations in which I placed a check box inside a button and was able to demonstrate that if I were to use the click event on the check box the button would never see the click, but if I used a MouseLeftButtonDown, hey! Presto! the button did see the event.

This has now changed in Beta 2 to make Silverlight behave more like WPF. By and large (other than breaking my demo) this is a good thing.  The consistency now is that objects that directly derive from UI element do support event bubbling for the mouse events (that is,  Ellipse, Glyphs, Image, InkPresenter, Line, MediaElement, Path, Polygon, Polyline, Rectangle and TextBlock.)  In addition, the container classes do.

Thus, if you set up the following bizarre application in which you have a grid, with a grid in it, that contains a stack panel that in turn contains a rectangle, a TextBlock, a check box, a button and a listbox (the last to show the results)…

<UserControl x:Class="EventBubbling.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="800">
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid x:Name="InterimGrid" >
            <StackPanel x:Name="myStackPanel" Orientation="Vertical"  >
                <Rectangle x:Name="myRect" Width="30" Height="30" Fill="Blue"
                    Stroke="Red" StrokeThickness="2" Margin="0,10,0,10" />
                <TextBlock x:Name="myTextBlock" Text="Hello"  
                    HorizontalAlignment="Center" FontSize="14" Margin="0,10,0,10"/>
                <CheckBox x:Name="myCheckBox" Content="Check Me" Width="80" 
                    Height="40" Margin="0,10,0,10" HorizontalAlignment="Center" />
                <Button x:Name="myButton" Content="TinyButton" Height="30" 
                    Width="70" Margin="0,10,0,10" FontSize="12" HorizontalAlignment="Center" />
                <ListBox x:Name="Messages" Width="150" Height="400" />      
        </StackPanel>
      </Grid>
    </Grid>
</UserControl>

and you add MouseLeftButtonDown event handlers for everything (except the list box):

void Page_Loaded(object sender, RoutedEventArgs e)
{
    LayoutRoot.MouseLeftButtonDown += new MouseButtonEventHandler(
        LayoutRoot_MouseLeftButtonDown);
    InterimGrid.MouseLeftButtonDown += new MouseButtonEventHandler(
        InterimGrid_MouseLeftButtonDown);
    myStackPanel.MouseLeftButtonDown += new MouseButtonEventHandler(
        myStackPanel_MouseLeftButtonDown);
    myRect.MouseLeftButtonDown += new MouseButtonEventHandler(
        myRect_MouseLeftButtonDown);
    myTextBlock.MouseLeftButtonDown += new MouseButtonEventHandler(
        myTextBlock_MouseLeftButtonDown);
    myCheckBox.MouseLeftButtonDown += new MouseButtonEventHandler(
        myCheckBox_MouseLeftButtonDown);
    myButton.MouseLeftButtonDown += new MouseButtonEventHandler(
        myButton_MouseLeftButtonDown);
}

 

 

 

where all the handlers do the same thing, they add to the list box (there are more efficient ways to write this!)

void InterimGrid_MouseLeftButtonDown(
    object sender, MouseButtonEventArgs e)
{
    Messages.Items.Add(" InterimGrid ");
}

What you find is that when you click on the rectangle or the text block the event bubbles all the way to the top most grid, but if you click on the checkbox or the button the event is “handled” by that control and is not bubbled at all.

BubblingNoMore

In the image, I’ve clicked on the rectangle and the event was registered by the rectangle, the StackPanel that encloses it, the Grid that holds the StackPanel and the outermost grid.  I’m now clicking on the button, and while the button is registering the mouse down, it is not passing it along to anyone else.

One fascinating aspect of this (at least to me, but I don’t get out much) is that if I inject a button into the middle of the stream, by putting the rectangle, textblock checkbox and button inside an outer button…

<UserControl x:Class="EventBubbling.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="600">
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid x:Name="InterimGrid" >
            <Grid.RowDefinitions>
                <RowDefinition Height="120" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <Button x:Name="OuterButton" Width="300" Height="100" Grid.Row="0">
                <StackPanel x:Name="myStackPanel" Orientation="Horizontal"  >
                    <Rectangle x:Name="myRect" Width="50" Height="30" Fill="Blue"
                        Stroke="Red" StrokeThickness="2" Margin="5,0,5,0" />
                    <TextBlock x:Name="myTextBlock" Text="Hello"  
                        VerticalAlignment="Center" FontSize="14" Margin="5,0,5,0"/>
                    <CheckBox x:Name="myCheckBox" Content="Check Me" Width="80" 
                        Height="40" Margin="5,0,5,0" VerticalAlignment="Center" />
                    <Button x:Name="myButton" Content="TinyButton" Height="30" 
                        Width="70" Margin="5,0,5,0" FontSize="12" VerticalAlignment="Center" />
                </StackPanel>
            </Button>
            <ListBox x:Name="Messages" Width="150" Height="400" Grid.Row="1"/>      
        </Grid>
    </Grid>
</UserControl>

The key changes are that I’ve created two rows (one for the controls, one for the list box) and injected a button above the stack panel that holds the stack panel and all its contents (now horizontal). Let’s run the same experiment…

BubblingNoMore2

Once again, I clicked on the Rectangle, and then was clicking on the button when I took the image. Once again the button had no bubbling, but notice that the Rectangle did not bubble as far as it had previously. After it hit the stack panel it hit the outer button which ate the MouseLeftButtonDown event, and did not pass it along to any containers above it.

All of this is as it should be, and will end a lot of confusion for folks coming over from WPF, but if you learned about bubbling from me, then you’ll want to know about this change.

(Source code posted when Beta2 Ships)

Thanks

Published Tuesday, June 03, 2008 3:57 PM by jesseliberty

Comments

# re: Beta 2 Event Bubbling

That does make more sense to me now.  

I eagerly await more Beta 2 information as well (as well as a keyboard that corrects my spelling on the fly, that one may have to wait longer though)

:)

Tuesday, June 03, 2008 4:03 PM by johnnystock

# re: Beta 2 Event Bubbling

can we *see* the list of new features too? :D

Tuesday, June 03, 2008 8:09 PM by chris_vickerson

# Silverlight 2 - Beta 2 arrives this week!

Silverlight 2 - Beta 2 arrives this week!

Tuesday, June 03, 2008 10:06 PM by Page Brooks

# re: Beta 2 Event Bubbling

>> can we *see* the list of new features too <<

The minute I have a comprehensive list, I will publish it or a link to it.

Wednesday, June 04, 2008 8:39 AM by jesseliberty

# Dew Drop &ndash; June 4, 2008 | Alvin Ashcraft's Morning Dew

Pingback from  Dew Drop &ndash; June 4, 2008 | Alvin Ashcraft's Morning Dew

Wednesday, June 04, 2008 8:39 AM by Dew Drop – June 4, 2008 | Alvin Ashcraft's Morning Dew

# re: Beta 2 Event Bubbling

Is there any news about Expression blend 2.5 new beta

Wednesday, June 04, 2008 1:12 PM by kamii47

# Beta 2 Event Bubbling

Pingback from  Beta 2 Event Bubbling

Thursday, June 05, 2008 10:26 PM by Beta 2 Event Bubbling

# re: Beta 2 Event Bubbling

When I wire up a MouseLeftButtonDown event to a slider control the event is not raised when I click the button. Is this because the container it is in is handling the event?

My code no longer works;

           theSlider.MouseLeftButtonDown += new MouseButtonEventHandler(theSlider_MouseLeftButtonDown);

           theSlider.MouseEnter += new MouseEventHandler(theSlider_MouseEnter);

           theSlider.ValueChanged +=new RoutedPropertyChangedEventHandler<double>(theSlider_ValueChanged);

Will test the theory that something else is handling the event first.

thanks

Stephen

Tuesday, June 10, 2008 3:23 AM by Lyynx

# re: Beta 2 Event Bubbling

Jesse,

 Mmmm... I used the OnLButtonDown in the root canvas to perform drag and drop operations, now this doesn't work.

 As workarounds I have tought:

 - Convert all my textblocks to textboxes and subscribe to the Left Button Down event, but.. can I easily or manually resend the message to the root canvas?

 - A nasty trick is to place a transparent area, ... like we have done with the nasty HTML DIV's... but I think there must be a cleaner solution.

 Thanks,

   Braulio

Friday, June 13, 2008 3:51 AM by brauliod

# re: Beta 2 Event Bubbling

I've spent all day trawling Google, MSDN and Silverlight.net for an answer to firing MouseLeftButtonDown/Up events for a Slider, but thus far none of the solutions have worked.

I've tried putting grids / canvasses behind the slider, but it just doesn't fire when I use the slider. If I put a rectangle over the slider and make it invisible, I can't use the slider but the events do fire!

Please Jesse, could you fix it for me?!

Thanks,

Ellis

Thursday, June 26, 2008 7:03 PM by Flyte

# Quick note: New TechEd downloads | Tamir Khason - Just code

Pingback from  Quick note: New TechEd downloads | Tamir Khason - Just code

Thursday, January 01, 2009 3:50 AM by Quick note: New TechEd downloads | Tamir Khason - Just code

# Quick note: New TechEd downloads

[This blog was migrated. You will not be able to comment here. The new URL of this post is http://khason

Thursday, January 01, 2009 2:00 PM by Just Code - Tamir Khason

# re: Beta 2 Event Bubbling

Does anyone have a suggestion on how to capture events by default?

For instance, I have a window control

<UI:Window>

 <TextBlock Text="some text" />

 <Button />

</UI:Window>

Now when the button is clicked, the window does not get the focus (the button-lmd ate the event).

Of course this behaviour is undesirable for windows and form controls.

Is there a way to fix this, without registering mass child eventhandlers?

Thanks, regards,

Martien

Wednesday, September 02, 2009 8:15 AM by martiendejong2008