首页 > 解决方案 > 在 wpf 中,装饰器可以捕获路由命令吗?

问题描述

我有一个 listboxitem,单击它时会生成一个装饰器,其中包含一个由文本框标签和 MediaElement 组成的自定义控件。一切都很好,并且播放了选定的电影。列表框被子类化为“ChartCanvas”的自定义控件。

我的问题:我在视觉树的不同部分拥有电影的控件。将播放电影的命令发送到“ChartCanvas”很简单,但我不知道如何将此命令发送到覆盖的装饰器控件。

创建装饰器的基本代码是:

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.");

        }

        public void Add()
        {   // These commands are absolutely needed for correct MediaElement/Adorner usage.
            AddLogicalChild(m_element);
            AddVisualChild(m_element);  

       ... ...
        }

PlayMovieCommand 的 ChartCanvas 代码:

private ICommand _playMovie;
        public ICommand PlayMovieCommand
        {
            get
            {
                if (_playMovie == null)
                {
                    _playMovie = new RelayCommand(
                        p => true,
                        p => this.PlayMovie());
                }
                return _playMovie;
            }
        }

private void PlayMovie()
        {   
            Commands.PlayMovieCommand.Execute(null,null);          
        }

而在 MovieControl 装饰器中——这个代码永远不会到达:

public MovieControlForChartCanvas()
        {
            InitializeComponent();

            CommandBindings.Add(new CommandBinding(Commands.PlayMovieCommand, OnPlayMovieCommand));

        }

简而言之,装饰器如何捕获路由命令?

感谢您的任何帮助。

标签: wpfadornerrouted-commands

解决方案


恐怕您无法使用路由命令来实现这一点,因为它们仅限于从焦点元素中搜索元素树并向上搜索具有匹配命令绑定的元素。

相反,您可以引发事件或从一个组件向另一个组件发送消息。如果您不想实现自己的,那么常见的 MVVM 框架中有可用的实现。

例如,您可以使用EventAggregatorin Prism

确保在应用程序中使用它的单个实例。如果你还没有实现依赖注入,你可以例如定义一个静态属性App.xaml.cs

public partial class App : Application
{
    public static Prism.Events.IEventAggregator EventAggregator { get; } 
        = new Prism.Events.EventAggregator();
}

然后,您将使用它来订阅和发布来自应用程序不同部分的事件。

ChartCanvas(发布):

App.EventAggregator.GetEvent<PlayMovieEvent>().Publish();

装饰者(订阅):

App.EventAggregator.GetEvent<PlayMovieEvent>()
    .Subscribe(() => { /* play movie...*/ });

有效载荷只是一个简单的类型:

public class PlayMovieEvent : Prism.Events.PubSubEvent { }

您将在docs中找到有关此的更多信息。


推荐阅读