如何从子控件使用 Command.CanExecute

本文关键字:Command CanExecute 控件 | 更新日期: 2023-09-27 18:30:49

这是设置(删除了无关的布局代码):

Window.xaml

<Button Name="btn_Next" Command="NextPage">Next</Button>
<ContentControl Name="contentControl1" >
        <Binding ElementName="MainWindow" Path="CurrentPage"/>
</ContentControl>

Window.xaml.cs 构造函数

  var nextCommand = new CommandBinding(NavigationCommands.NextPage);
  nextCommand.CanExecute += nextCommand_CanExecute;
  nextCommand.Executed += nextCommand_Executed;
  CommandBindings.Add(nextCommand);

这在基本示例中非常有效,nextCommand_CanExecute检查当前页面是否是最后一页。但是,该逻辑目前仅检查数组,仅适用于线性导航。但是,导航将是树状的,这将不起作用,其中contentControl1中的项目有时会向不同的方向分支。因此,我希望CurrentPage的用户控件有机会覆盖CanExecute。我的问题是我无法弄清楚如何让UserControl开始CanExecute。我尝试使用许多CommandTarget设置无济于事......我的子控件从未触发过CanExecute方法。我什至尝试在父窗口的 CanExecute 中使用e.ContinueRouting = true。这是用户控制代码,以防万一。

用户控制控制器:

  var nextCommand = new CommandBinding(NavigationCommands.NextPage);
  nextCommand.CanExecute += nextCommand_CanExecute;
  CommandBindings.Add(nextCommand);

用户控件可以执行方法:

private void nextCommand_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
  e.CanExecute = false;
  e.Handled = true;
}

如何从子控件使用 Command.CanExecute

路由命令事件从可视化树的根向下隧道到启动它们的控件,然后冒泡回来。Josh Smith 关于路由命令的文章很好地描述了它的工作原理(特别是"路由"部分)http://joshsmithonwpf.wordpress.com/2008/03/18/understanding-routed-commands/。

这里的问题是,您的用户控件(在内容控件内部)不是发出命令的按钮的"祖先",因此路由事件永远不会到达它(即使是传递)。鉴于可视化树的结构方式,我认为路由命令对您来说是不够的。

我想到的第一个解决方案是装配您自己的机制,用于将 CanExecute/Execute 逻辑委派给用户控件。也许您可以定义一个由所有此类控件实现的基类或接口,该基类或接口定义了所需的各种命令CanExecute/Execute方法。然后,您可以只使用一个顶级实现,它将当前加载的控件强制转换为接口/基类类型并调用适当的方法。