• WPF之坑——ICommandSource与RoutedUICommand


    最近在项目中自己写了一个控件A,继承自contentcontrol,实现了icommandsource接口。(因需求特殊并没有使用buttonbase及它的派生类为基类),控件A在测试程序中运转良好,绑定的命令响应方法能够被正确执行。下边代码是控件A执行命令的部分:

    RoutedEventArgs rea = new RoutedEventArgs(Button.ClickEvent, this);
    RaiseEvent(rea);
    
    if (!rea.Handled && Command != null)
    {
        Command.Execute(CommandParameter);
    }
    

      

    但在实现项目中,我将控件A放在了另一个较为复制杂的控件B的template中,并在控件B的commandbindings中设置了命令绑定,命令使用的是WPF原生命令类型RoutedUICommand。这个时候诡异的事件发生了,不论我怎么在template里边设置控件A的commandtarget属性,上边代码执行了Command.Execute(CommandParameter)这句之后,B绑定的命令响应方法都不会被调用。

    之后在群里问了一些大神,都没有得到解决方法,于是乎查了下.net码源,看看buttonbase是如何处理这个问题。

    不看不知道,一看吓一跳,在buttonbase中处理命令时,用到了大量的.net项目里的internal类或方法(微软这是成心留一手啊!)

    #from buttonbase.cs        
    /// <summary> /// This virtual method is called when button is clicked and it raises the Click event /// </summary> protected virtual void OnClick() { RoutedEventArgs newEvent = new RoutedEventArgs(ButtonBase.ClickEvent, this); RaiseEvent(newEvent); MS.Internal.Commands.CommandHelpers.ExecuteCommandSource(this); }

      #from CommandHelpers.cs

    internal static void ExecuteCommandSource(ICommandSource commandSource)
    {
           CriticalExecuteCommandSource(commandSource, false);
     }
    
    
    internal static void CriticalExecuteCommandSource(ICommandSource commandSource, bool userInitiated)
    {
          ICommand command = commandSource.Command;
          if (command != null)
          {
               object parameter = commandSource.CommandParameter;
               IInputElement target = commandSource.CommandTarget;
    
               RoutedCommand routed = command as RoutedCommand;
               if (routed != null)
               {
                    if (target == null)
                    {
                        target = commandSource as IInputElement;
                    }
                    if (routed.CanExecute(parameter, target))
                    {
                        routed.ExecuteCore(parameter, target, userInitiated);
                    }
               }
               else if (command.CanExecute(parameter))
                {
                     command.Execute(parameter);
                }
          }
    }
    

     从上边.net这几段代码里我们可以看到,buttonbase在执行命令里的时候,使用的是 CommandHelpers这个内部类中定义的方法,而这个方法的核心逻辑是先判断使用的命令是不是RoutedCommand类型,如果是的话则可能会使用RoutedCommand的内方法ExecuteCore去执行命令,而在这个方法中才有commandtarget这个参数。

    总结一下,如果你的控件不是继承自buttonbase,那么就不能使用RoutedCommand.RoutedCommand这个内部方法,不能使用这个内部方法那么RoutedCommand就不会认你自己设置的commandtarget,那么如果.net库自己找到target不对,你再怎么设置也是徒劳。。。(我感觉被微软深深伤害了)

    说明白点,不要把自己实现icommandsource的类型与routedcommand搭配使用!

  • 相关阅读:
    web常用自动化库——selenium总结(转)
    前端框架面试题
    SpringBoot整合Knife4j展示更美观的API文档
    JUC- ThreadLocal学习笔记
    JUC-ThreadPool线程池的使用与学习
    Java8 新特性
    SpringBoot 整合FreeMarker进行邮件发送
    IDEA 打开别人的项目的是Maevn插件依赖出错问题处理
    Liunx常用指令备查
    第四次作业
  • 原文地址:https://www.cnblogs.com/GuoRL/p/5778868.html
Copyright © 2020-2023  润新知