我可以使用 DataTemplate 将 ContextMenu 应用到 ContextMenuViewModel 吗?
我有一个代表我的上下文菜单 (IContextMenu) 的 ViewModel (AbstractContextMenu),并使用 DataTemplate 将真正的 ContextMenu 绑定到它:
<DataTemplate DataType="{x:Type local:AbstractContextMenu}">
<ContextMenu x:Name="contextMenu"
ItemsSource="{Binding Path=(local:IContextMenu.Items)}"
IsEnabled="{Binding Path=(local:IContextMenu.IsEnabled)}"/>
</DataTemplate>
然后我有一个用于测试的虚拟 ConcreteContextMenu,它仅继承自 AbstractContextMenu。 AbstractContextMenu 只是实现此接口:
public interface IContextMenu : IExtension
{
IEnumerable<IMenuItem> Items { get; set; }
bool IsEnabled { get; set; }
}
我将它用作另一个 ViewModel 对象的属性:
public IContextMenu ContextMenu
{
get
{
return m_ContextMenu;
}
protected set
{
if (m_ContextMenu != value)
{
m_ContextMenu = value;
NotifyPropertyChanged(m_ContextMenuArgs);
}
}
}
private IContextMenu m_ContextMenu = new ConcreteContextMenu();
static readonly PropertyChangedEventArgs m_ContextMenuArgs =
NotifyPropertyChangedHelper.CreateArgs<AbstractSolutionItem>(o => o.ContextMenu);
然后我将 StackPanel 绑定到该 ViewModel,并将 StackPanel 上的 ContextMenu 属性绑定到 ViewModel 的 ContextMenu 属性:
<StackPanel Orientation="Horizontal"
ContextMenu="{Binding Path=(local:AbstractSolutionItem.ContextMenu)}"
ContextMenuOpening="stackPanel_ContextMenuOpening">
<!-- stuff goes in here -->
</StackPanel>
当我运行此命令时,ContextMenuOpening StackPanel 上的事件被触发,但 ContextMenu 永远不会显示。我不确定我是否可以这样做(使用 DataTemplate 将 ContextMenu 应用于 ContextMenu ViewModel)。有人知道吗?
I have a ViewModel (AbstractContextMenu) that represents my context menu (IContextMenu), and I bind a real ContextMenu to it with a DataTemplate:
<DataTemplate DataType="{x:Type local:AbstractContextMenu}">
<ContextMenu x:Name="contextMenu"
ItemsSource="{Binding Path=(local:IContextMenu.Items)}"
IsEnabled="{Binding Path=(local:IContextMenu.IsEnabled)}"/>
</DataTemplate>
Then I have a dummy ConcreteContextMenu for testing that just inherits from AbstractContextMenu. AbstractContextMenu just implements this interface:
public interface IContextMenu : IExtension
{
IEnumerable<IMenuItem> Items { get; set; }
bool IsEnabled { get; set; }
}
I'm using it as a property of another ViewModel object:
public IContextMenu ContextMenu
{
get
{
return m_ContextMenu;
}
protected set
{
if (m_ContextMenu != value)
{
m_ContextMenu = value;
NotifyPropertyChanged(m_ContextMenuArgs);
}
}
}
private IContextMenu m_ContextMenu = new ConcreteContextMenu();
static readonly PropertyChangedEventArgs m_ContextMenuArgs =
NotifyPropertyChangedHelper.CreateArgs<AbstractSolutionItem>(o => o.ContextMenu);
Then I bind a StackPanel to that ViewModel and bind the ContextMenu property on the StackPanel to the ContextMenu property of the ViewModel:
<StackPanel Orientation="Horizontal"
ContextMenu="{Binding Path=(local:AbstractSolutionItem.ContextMenu)}"
ContextMenuOpening="stackPanel_ContextMenuOpening">
<!-- stuff goes in here -->
</StackPanel>
When I run this, the ContextMenuOpening event on the StackPanel is fired, but the ContextMenu is never displayed. I'm not sure if I can even do this (apply a ContextMenu to a ContextMenu ViewModel using a DataTemplate). Anyone know?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
AbstractSolutionItem.ContextMenu
的类型是什么?如果它对应于您问题中的 ContextMenu 属性,则问题可能是类型错误。FrameworkElement
的ContextMenu
属性需要一个实际的ContextMenu
,而不是IContextMenu
。尝试在调试应用程序时检查输出窗口 - 您可能会收到一条错误消息,指出这就是问题所在。无需使用
DataTemplate
来定义ContextMenu
,只需放入模板StackPanel.ContextMenu
的内容即可:这应该可以帮助您完成大部分工作那里。但是,仍然存在问题,因为
ContextMenu
不知道如何从IMenuItem
创建MenuItem
。要解决此问题,请为ContextMenu
创建一个ItemTemplate
,它将IMenuItem
的成员绑定到 `MenuItem。What is the type of
AbstractSolutionItem.ContextMenu
? If it corresponds to theContextMenu
property in your question, then the problem could be that the type is wrong. TheContextMenu
property ofFrameworkElement
is expecting an actualContextMenu
, not anIContextMenu
. Try checking the output window while debugging your app - you might get an error message stating that this is the problem.Instead of using a
DataTemplate
to define yourContextMenu
, just put the contents of the templateStackPanel.ContextMenu
:That should get you most of the way there. However, there is still a problem since the
ContextMenu
does not know how to create aMenuItem
from anIMenuItem
. To solve this, create anItemTemplate
for theContextMenu
, which binds members ofIMenuItem
to `MenuItem.您能否介绍一下
DataTemplate
中的ItemsSource
属性中使用的语法?使用括号通常意味着附加属性。并且Items
似乎不是由IContextMenu
定义的附加属性(因为接口无法定义这样的属性)。DataTemplate 链接到一个
AbstractContextMenu
类型的对象,该对象具有一个名为Items
的属性。因此,DataTemplate 可以像这样简单地引用它:如果
AbstractSolutionItem
类是StackPanel
的 VM,则可以这样绑定它:当然,DataTemplate 必须是从 StackPanel 中“可访问”。
Could you shed some light on the syntax used in the
ItemsSource
property in theDataTemplate
? Using parentheses usually means an attached property. AndItems
does not seem to be an attached property defined byIContextMenu
(as an interface cannot define such a property).The DataTemplate is linked to an object of type
AbstractContextMenu
which has a property calledItems
. So, the DataTemplate could simply reference it like this:If the
AbstractSolutionItem
class is the VM of theStackPanel
, you could bind it like this:Of course, the DataTemplate must be "accessible" from the StackPanel.
将视图(本例中为 StackPanel)的 ContextMenu 属性绑定到 ViewModel 的 ContextMenu 属性,并向绑定提供 IValueConverter,该绑定将创建 ContextMenu 对象并将 IContextMenu 设置为其 DataContext。
Bind the ContextMenu property of your view (StackPanel in this scenario) to the ContextMenu property of your ViewModel and provide a IValueConverter to the binding that will create the ContextMenu object and set the IContextMenu to it's DataContext.