A contrived example: Window -Grid --StackPanel ---Slider ---Slider
Both sliders use Interaction.Triggers to send a custom-command defined in codebehind. Each of the visual parents define a CommandBinding to tie this Test command and invoke an Executed handler in code behind. Only the handler for the closest ancestor is hit: e.g. if all three bindings are in xaml, then only StackPanel_CommandBinding_Executed breakpoint is hit. If I comment-out the CommandBinding for StackPanel, then the next parent higher handler will be hit (StackPanel_CommandBinding_Executed).
Though this example uses Interaction, I did try the same with a simpler Button Command. Same result.
I presume that I had the wrong expectations here. I had thought that this bubbling command would check handlers from the focusing Slider on-up the Visual Tree. At each level up, if an Executed handler was bound for the command, it would be called. I expected each of the handlers would be called in turn: StackPanel, Grid, the Window. I've read that Bubbling did not stop just because a handler was found at a given level, but this is not my experience.
// in RoutedCommandStackOverflow ns
public class CustomCommands
{
public static readonly RoutedUICommand Test
= new RoutedUICommand("Test","Test",typeof(CustomCommands));
}
//the Executed handlers are like:
private void StackPanel_CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
{
Debug.Assert(e.Handled == false);
Debug.WriteLine("StackPanel_CommandBinding_Executed");
}
<Window x:Class="RoutedCommandStackOverflow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:iAct="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:local="clr-namespace:RoutedCommandStackOverflow"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.CommandBindings>
<CommandBinding Command="{x:Static local:CustomCommands.Test}" Executed="Window_CommandBinding_Executed"/>
</Window.CommandBindings>
<Grid>
<Grid.CommandBindings>
<CommandBinding Command="{x:Static local:CustomCommands.Test}" Executed="Grid_CommandBinding_Executed"/>
</Grid.CommandBindings>
<StackPanel>
<StackPanel.CommandBindings>
<CommandBinding Command="{x:Static local:CustomCommands.Test}" Executed="StackPanel_CommandBinding_Executed"/>
</StackPanel.CommandBindings>
<Slider Name="gridSlider1" Margin="10">
<iAct:Interaction.Triggers>
<iAct:EventTrigger EventName="GotFocus">
<iAct:InvokeCommandAction Command="{x:Static local:CustomCommands.Test}"/>
</iAct:EventTrigger>
</iAct:Interaction.Triggers>
</Slider>
<Slider Name="gridSlider2" Margin="10">
<iAct:Interaction.Triggers>
<iAct:EventTrigger EventName="GotFocus">
<iAct:InvokeCommandAction Command="{x:Static local:CustomCommands.Test}"/>
</iAct:EventTrigger>
</iAct:Interaction.Triggers>
</Slider>
</StackPanel>
</Grid>