在 MenuItem 的 CustomControls 中触发和捕获自定义 RoutedCommands
Firing and Capturing of Custom RoutedCommands within CustomControls for MenuItems
WPF。 .NET 4.6
我正在尝试学习 RoutedCommands。在下面的代码中,我的愿望是让我的自定义 class 的 MenuItem 通过触发自定义路由命令 来响应用户点击,该命令被 监听 parent menuitem. 当parent menuitem接收到它包含的children的routedcommand时,就是设置一个dependency 属性 允许visual tree中的其他元素绑定使用 ElementName 绑定。到目前为止,我一直无法在父容器中捕获命令——所以我不确定它是否真的在冒泡。
- 命令 ChangeInkAttributes 如何通过元素树向上路由到顶部 "InkMenu" 元素?
- 子元素如何,例如"InkAndGestures",触发 routedcommand,ChangeInkAttributes,从 自定义控件,InkMenuItem?
- 父容器"InkMenu"如何捕获路由命令"InkAndGestures"?(最好在自定义控件中捕获路由命令——这是甚至可能?)
注意:我想避免代码隐藏中的 any/all 代码。
我很感激任何帮助,因为 Google 的彻底搜索未能展示这种方法的一个很好的例子。
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");
}
}
A RoutedCommand
从聚焦元素搜索可视化树并向上搜索具有匹配 CommandBinding
的元素,为该特定 CommandBinding
执行 Execute
委托然后停下来。
它不会像 Microsoft 的 Nick Kramer 在这里所说的那样进一步路由或冒泡:https://www.vistax64.com/avalon/852-routedcommand-doesnt-route-ui-tree.html。
在拔掉我遗漏的头发后,我可以放心地保证@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);
}
希望这对某人有所帮助。
WPF。 .NET 4.6
我正在尝试学习 RoutedCommands。在下面的代码中,我的愿望是让我的自定义 class 的 MenuItem 通过触发自定义路由命令 来响应用户点击,该命令被 监听 parent menuitem. 当parent menuitem接收到它包含的children的routedcommand时,就是设置一个dependency 属性 允许visual tree中的其他元素绑定使用 ElementName 绑定。到目前为止,我一直无法在父容器中捕获命令——所以我不确定它是否真的在冒泡。
- 命令 ChangeInkAttributes 如何通过元素树向上路由到顶部 "InkMenu" 元素?
- 子元素如何,例如"InkAndGestures",触发 routedcommand,ChangeInkAttributes,从 自定义控件,InkMenuItem?
- 父容器"InkMenu"如何捕获路由命令"InkAndGestures"?(最好在自定义控件中捕获路由命令——这是甚至可能?)
注意:我想避免代码隐藏中的 any/all 代码。
我很感激任何帮助,因为 Google 的彻底搜索未能展示这种方法的一个很好的例子。
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");
}
}
A RoutedCommand
从聚焦元素搜索可视化树并向上搜索具有匹配 CommandBinding
的元素,为该特定 CommandBinding
执行 Execute
委托然后停下来。
它不会像 Microsoft 的 Nick Kramer 在这里所说的那样进一步路由或冒泡:https://www.vistax64.com/avalon/852-routedcommand-doesnt-route-ui-tree.html。
在拔掉我遗漏的头发后,我可以放心地保证@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);
}
希望这对某人有所帮助。