WPF. .NET 4.6
I'm trying to learn RoutedCommands. In the below code, my desire is to have my custom class of MenuItem respond to the user click by firing a custom routedcommand which is listened to by the parent menuitem. When the parent menuitem receives the routedcommand from its contained children, it is to set a dependency property allowing other elements in the visual tree to bind using ElementName binding. So far, I have been unable to capture the command at the parent container--so I am not sure if it is actually bubbling at all.
Note: I would like to avoid any/all code in code-behind.
I appreciate any help with this as a thorough search with Google has failed to show a good example of this approach.
TIA
As as example:
<pn:InkMenuItem x:Name="InkMenu" Header="Ink" > <---**Parent containter to set
the dependency property and provide for ElementName binding.
THESE ARE THE CHILDREN WHICH SHOULD SEND THE COMMAND TO THE PARENT "InkMenu"
<pn:InkMenuItem Header="Pen" />
<pn:InkMenuItem Header="HighLighter" />
<Separator />
<pn:InkMenuItem Header="RePen Selection" />
<pn:InkMenuItem Header="Select Strokes" />
<pn:InkMenuItem Header="Select All Strokes" />
<Separator />
<pn:InkMenuItem Header="Erase By Stroke" />
<pn:InkMenuItem Header="Erase By Point" />
<pn:InkMenuItem Header="Clear Strokes" />
<Separator />
<pn:InkMenuItem Header="Show Recognition Layout" />
<pn:InkMenuItem x:Name="InkAndGestures" Header="Ink And Getsures" IsCheckable="True"/>
</pn:InkMenuItem>
I've defined the InkMenuItem customcontrol simply as:
Generic.XAML:
<Style TargetType="{x:Type local:InkMenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}"/>
InkMenuItem.cs:
public class InkMenuItem : MenuItem
{
public static RoutedUICommand ChangeInkAttributes { get; }
static InkMenuItem()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(InkMenuItem), new FrameworkPropertyMetadata(typeof(InkMenuItem)));
//Instanciate the command
ChangeInkAttributes = new RoutedUICommand("Change Ink Attributes", "ChangeInkAttributes", typeof(InkMenuItem));
//Create the command binding
CommandManager.RegisterClassCommandBinding(typeof(InkMenuItem),
new CommandBinding(
/*Command Object */ ChangeInkAttributes,
/*Execute*/ ChangeInkAttributes_Executed,
/*Can Execute? */ ChangeInkAttributes_CanExecute));
}
public static void ChangeInkAttributes_Executed(object sender, ExecutedRoutedEventArgs e)
{
InkMenuItem inkmenuitem = sender as InkMenuItem;
CommandParameter parameter = e.Parameter as CommandParameter;
if (parameter != null)
parameter.CanEditBeExecuted = true;
if (inkmenuitem != null)
inkmenuitem.changeInkAttributes();
}
public static void ChangeInkAttributes_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true; // can this command be executed?
e.Handled = false; // has this event been handled?
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
}
// Raise the MyChecked event when the InkMenuItem is clicked
protected override void OnClick()
{
// base.OnClick();
ChangeInkAttributes.Execute(null,this);
}
private void changeInkAttributes()
{
var h = Header.ToString();
MessageBox.Show(h+"23");
}
}
A RoutedCommand
searches the visual tree from the focused element and up for an element that has a matching CommandBinding
, executes the Execute
delegate for this particular CommandBinding
and then stops.
It doesn't route or bubble up any further as Nick Kramer of Microsoft has stated here: https://www.vistax64.com/avalon/852-routedcommand-doesnt-route-ui-tree.html.