WPF。 .NET 4.6
我正在尝试学习RoutedCommands。在下面的代码中,我希望我的自定义类MenuItem通过触发父 menuitem的已侦听的自定义路由命令来响应用户点击。当父菜单项从其包含的子节点接收routedcommand时,它将设置一个依赖项属性,允许可视树中的其他元素使用ElementName绑定进行绑定。到目前为止,我一直无法在父容器中捕获命令 - 所以我不确定它是否真的冒泡了。
注意:我想避免代码隐藏中的任何/所有代码。
我感谢任何帮助,因为对谷歌进行全面搜索未能展示出这种方法的一个很好的例子。
TIA
例如:
<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>
我将InkMenuItem自定义控件简单地定义为:
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");
}
}
答案 0 :(得分:1)
RoutedCommand
从焦点元素中搜索可视树,向上搜索具有匹配CommandBinding
的元素,为此特定Execute
执行CommandBinding
委托,然后停止。
微软的Nick Kramer在此声明:https://www.vistax64.com/avalon/852-routedcommand-doesnt-route-ui-tree.html。
它没有任何进一步的路由或冒泡。答案 1 :(得分:1)
拉了我留下的小头发之后,我可以放心地保证@ mm8是100%正确的。但是,我确实希望这个泡沫无论如何。所以,我改变了
ChangeInkAttributes_Executed事件以在其父InkMenuItem上重新抛出自身:
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();
// this only causes a loop, it does not bubble.
// inkmenuitem.RaiseEvent(e);
InkMenuItem parent = inkmenuitem.Parent as InkMenuItem;
if (parent != null)
parent.RaiseEvent(e);
}
希望这有助于某人。