You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF中Adorner装饰器是否可以捕获RoutedCommand路由命令?

WPF Adorner捕获RoutedCommand解决方案

问题核心原因

  • RoutedCommand的路由依赖指定的触发源(Execute方法的第二个参数),现有代码调用Commands.PlayMovieCommand.Execute(null,null)时传入的源为null,路由只会在当前ChartCanvas范围内查找绑定,不会流向Adorner控件。
  • Adorner的视觉树默认挂载在独立的AdornerLayer下,和ChartCanvas的主视觉树平级,没有主动指定源的情况下路由不会主动流向Adorner节点。

可落地解决方案

方案1:指定命令路由源(最推荐,改动最小)

首先在ChartCanvas中存储当前激活的影片Adorner实例,触发命令时指定Adorner内的自定义控件为路由源:

  1. ChartCanvas类中新增字段存储当前激活的Adorner:
// ChartCanvas类中新增
private UIElementAdorner _activeMovieAdorner;
  1. 点击ListBoxItem生成Adorner的逻辑中,给上述字段赋值:
// 生成Adorner的代码处补充
_activeMovieAdorner = 新建的UIElementAdorner实例;
  1. 修改ChartCanvas的PlayMovie方法:
private void PlayMovie()
{   
    // 传入Adorner承载的自定义控件作为路由源
    Commands.PlayMovieCommand.Execute(null, _activeMovieAdorner?.m_element);          
}

该方案直接让路由从目标MovieControl开始查找绑定,可直接触发已经写好的OnPlayMovieCommand逻辑。

方案2:Adorner层添加命令中转绑定

如果场景支持同时存在多个影片Adorner,需要批量触发命令,可以在UIElementAdorner的构造函数中添加命令绑定中转:

public UIElementAdorner(UIElement adornedElement, UIElement element) : base(adornedElement)
{
    m_element = element;
    _adornedElement = adornedElement as Border;

    if (_adornedElement is null)
        throw new ArgumentException("This adorner requires a Border element of sizing in MeasureOverride and Arrangement.");

    // 新增命令中转绑定
    CommandBindings.Add(new CommandBinding(Commands.PlayMovieCommand, (sender, e) =>
    {
        if (m_element is IInputElement target)
        {
            Commands.PlayMovieCommand.Execute(e.Parameter, target);
        }
        e.Handled = false;
    }));
}

方案3:直接调用(最简场景适用)

如果每次只会存在一个激活的影片Adorner,可直接暴露Adorner内部的MovieControl实例,在PlayMovie中直接调用播放方法,跳过路由命令的复杂逻辑,避免路由问题。

注意事项

  • 使用RoutedCommand时必须确保Execute方法的第二个参数不为null,否则路由无法正常传递。
  • Adorner的逻辑树和视觉树独立于被装饰元素的主树,需要主动关联才能参与路由流程。

内容的提问来源于stack exchange,提问作者Alan Wayne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 18:24:03