代码之家  ›  专栏  ›  技术社区  ›  Mark A. Donohoe

如何被动响应RoutedCommand?

  •  0
  • Mark A. Donohoe  · 技术社区  · 6 年前

    我们的应用程序基于一堆页面,这些页面只是 FrameworkElement . 主窗口维护该堆栈并使用内置的 Close 命令关闭它们,只需将它们从堆栈中弹出即可。

    这件事似乎是正确的。

    现在,由于该页面实际上会在窗口之前获取事件( 命令是通过“冒泡事件”实现的。)我们认为我们所要做的就是在页面上设置命令绑定,然后在处理程序中设置 e.Handled 如果设置为false,则它将继续运行到窗口。

    这是页面中的代码( InitializeCommands 是从构造函数调用的)。。。

    private void InitializeCommands(){
    
        CommandBindings.Add(
            new CommandBinding(ApplicationCommands.Close, Close_Execute, Close_CanExecute)
        );
    }
    
    private void Close_CanExecute(object sender, CanExecuteRoutedEventArgs e){
        // True executes this handler, but blocks the one in the window
        // False executes the one in the window, but ignores this one
        e.CanExecute = true;
    
        // Doesn't seem to have any effect
        e.Handled = false;
    }
    private void Close_Execute(object sender, ExecutedRoutedEventArgs e){
        Console.WriteLine("I want to respond passively!");
        // Doesn't seem to have any effect
        e.Handled = false;
    }
    

    但是,无论我们将该属性设置为什么,该命令都不会进入主窗口。如果我们删除页面中的命令绑定,它将再次工作,证明页面正在吞咽命令,而不管该属性如何。

    那么,你要做什么才能让页面听 被动事件?

    2 回复  |  直到 6 年前
        1
  •  0
  •   Mark A. Donohoe    6 年前

    internal void OnExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        if (!e.Handled)
        {
            if (e.RoutedEvent == CommandManager.ExecutedEvent)
            {
                if (this.Executed != null && CheckCanExecute(sender, e))
                {
                    this.Executed(sender, e);
                    e.Handled = true;
                }
            }
            else if (this.PreviewExecuted != null && CheckCanExecute(sender, e))
            {
                this.PreviewExecuted(sender, e);
                e.Handled = true;
            }
        }
    }
    

    正如您所看到的,如果您为CanExecute返回true,那么这些命令就会被吃掉。

    您可能想看看CompositeCommand。那更适合你。创建绑定到框架的全局CompositeCommand,然后可以将不同的视图附着到该框架。不同的实现可以有不同的方法来确定命令的多个订阅者的行为。即所有必须返回canExecute、任何必须返回、仅进入活动视图等。

    编辑:CompositeCommand最初是Prism的一部分,但您可以找到一个独立的实现,也可以直接从Prism中删除该实现:

    https://github.com/PrismLibrary/Prism/blob/master/Source/Prism/Commands/CompositeCommand.cs

        2
  •  0
  •   SledgeHammer    6 年前

    另外一个想法是查看AddHandler()方法。让我们为所有子事件添加一个事件处理程序。例如,为了控制面包屑,我可以:

    AddHandler(BreadcrumbSplitButton.ClickEvent,new RoutedEventHandler(OnBreadcrumbSplitButtonClick));

    在BreadCrumb类中,侦听来自所有子BreadcrumbSplitButtons的ClickEvent。

    推荐文章