在 wpf 中,装饰器可以捕获路由命令吗?
In wpf, can an adorner catch a routed command?
我有一个 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));
}
简而言之,装饰器如何捕获路由命令?
感谢您的帮助。
恐怕您无法使用路由命令来实现此功能,因为它们仅限于从聚焦元素搜索元素树并向上搜索具有匹配命令绑定的元素。
相反,您可以引发事件或从一个组件向另一个组件发送消息。如果您不想实现自己的框架,可以在常见的 MVVM 框架中找到可用的实现。
例如,您可以在 Prism 中使用 EventAggregator
。
确保在您的应用程序中使用它的单个实例。如果你还没有实现依赖注入,你可以在 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...*/ });
payload只是一个简单的类型:
public class PlayMovieEvent : Prism.Events.PubSubEvent { }
您可以在 docs.
中找到更多相关信息
我有一个 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));
}
简而言之,装饰器如何捕获路由命令?
感谢您的帮助。
恐怕您无法使用路由命令来实现此功能,因为它们仅限于从聚焦元素搜索元素树并向上搜索具有匹配命令绑定的元素。
相反,您可以引发事件或从一个组件向另一个组件发送消息。如果您不想实现自己的框架,可以在常见的 MVVM 框架中找到可用的实现。
例如,您可以在 Prism 中使用 EventAggregator
。
确保在您的应用程序中使用它的单个实例。如果你还没有实现依赖注入,你可以在 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...*/ });
payload只是一个简单的类型:
public class PlayMovieEvent : Prism.Events.PubSubEvent { }
您可以在 docs.
中找到更多相关信息