I would like to avoid having to build a menu manually in XAML or code, by binding to a list of ICommand
-derived objects. However, I'm experiencing a bit of a problem where the resulting menu has two levels of menu-items (i.e. each MenuItem
is contained in a MenuItem
):
我想通过绑定到ICommand派生对象列表来避免在XAML或代码中手动构建菜单。但是,我遇到了一个问题,结果菜单有两级菜单项(即每个MenuItem包含在MenuItem中):
alt text http://i47.tinypic.com/j63lg2.png
替代文字http://i47.tinypic.com/j63lg2.png
My guess is that this is happening because WPF is automatically generating a MenuItem
for my binding, but the "viewer" I'm using actually already is a MenuItem
(it's derived from MenuItem
):
我的猜测是这种情况正在发生,因为WPF会自动为我的绑定生成一个MenuItem,但我实际使用的“viewer”是一个MenuItem(它是从MenuItem派生的):
<ContextMenu
x:Name="selectionContextMenu"
ItemsSource="{Binding Source={x:Static OrangeNote:Note.MultiCommands}}"
ItemContainerStyleSelector="{StaticResource separatorStyleSelector}">
<ContextMenu.ItemTemplate>
<DataTemplate>
<Viewers:NoteCommandMenuItemViewer
CommandParameter="{Binding Source={x:Static OrangeNote:App.Screen}, Path=SelectedNotes}" />
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
(The ItemContainerStyleSelector is from http://bea.stollnitz.com/blog/?p=23, which allows me to have Separator
elements inside my bound source.)
(ItemContainerStyleSelector来自http://bea.stollnitz.com/blog/?p=23,它允许我在绑定源中包含Separator元素。)
So, the menu is bound to a collection of ICommand
s, and each item's CommandParameter
is set to the same global target (which happens to be a collection, but that's not important).
因此,菜单绑定到ICommands的集合,并且每个项的CommandParameter都设置为相同的全局目标(恰好是一个集合,但这并不重要)。
My question is, is there any way I can bind this such that WPF doesn't automatically wrap each item in a MenuItem
?
我的问题是,有什么方法可以绑定它,以便WPF不会自动包装MenuItem中的每个项目?
2 个解决方案
#1
2
I would be inclined to subclass ContextMenu and override GetContainerForItemOverride:
我倾向于继承ContextMenu并重写GetContainerForItemOverride:
public class ContextMenuWithNoteCommands : ContextMenu
{
protected virtual DependencyObject GetContainerForItemOverride()
{
return new NoteCommandMenuItemViewer();
}
}
Then set the CommandParameter binding in the NoteCommandMenuItemViewer style, or in ContextMenu.ItemContainerStyle, whichever is more appropriate.
然后在NoteCommandMenuItemViewer样式或ContextMenu.ItemContainerStyle中设置CommandParameter绑定,以更合适的方式。
This presumes you can't simply use ItemContainerStyle on a regular MenuItem to get the effect you want:
这假设你不能简单地在常规MenuItem上使用ItemContainerStyle来获得你想要的效果:
<ContextMenu ...>
<ContextMenu.ItemContainerStyle>
<Style>
...
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
#2
3
Unfortunately, the best way I've found to work around this issue is to use a style for the MenuItems, rather than an ItemTemplate. Then each property in the style can be bound to properties on your object. Something like this, for example:
不幸的是,我发现解决这个问题的最好方法是使用MenuItems的样式,而不是ItemTemplate。然后,样式中的每个属性都可以绑定到对象上的属性。像这样的东西,例如:
<Style x:Key="SelectionContextMenuStyle" TargetType="MenuItem">
<Setter Property="Header" Value="{Binding Path=Text}" />
<Setter Property="Command" Value="{Binding Path=Command}" />
<Setter Property="CommandParameter" Value="{Binding Path=Parameter}" />
</Style>
It really seems like an ItemTemplate should work, and it would be the better way to go, but this is the only way I've found that actually works properly.
它看起来好像是一个ItemTemplate应该工作,这将是更好的方式,但这是我发现实际上正常工作的唯一方法。
#1
2
I would be inclined to subclass ContextMenu and override GetContainerForItemOverride:
我倾向于继承ContextMenu并重写GetContainerForItemOverride:
public class ContextMenuWithNoteCommands : ContextMenu
{
protected virtual DependencyObject GetContainerForItemOverride()
{
return new NoteCommandMenuItemViewer();
}
}
Then set the CommandParameter binding in the NoteCommandMenuItemViewer style, or in ContextMenu.ItemContainerStyle, whichever is more appropriate.
然后在NoteCommandMenuItemViewer样式或ContextMenu.ItemContainerStyle中设置CommandParameter绑定,以更合适的方式。
This presumes you can't simply use ItemContainerStyle on a regular MenuItem to get the effect you want:
这假设你不能简单地在常规MenuItem上使用ItemContainerStyle来获得你想要的效果:
<ContextMenu ...>
<ContextMenu.ItemContainerStyle>
<Style>
...
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
#2
3
Unfortunately, the best way I've found to work around this issue is to use a style for the MenuItems, rather than an ItemTemplate. Then each property in the style can be bound to properties on your object. Something like this, for example:
不幸的是,我发现解决这个问题的最好方法是使用MenuItems的样式,而不是ItemTemplate。然后,样式中的每个属性都可以绑定到对象上的属性。像这样的东西,例如:
<Style x:Key="SelectionContextMenuStyle" TargetType="MenuItem">
<Setter Property="Header" Value="{Binding Path=Text}" />
<Setter Property="Command" Value="{Binding Path=Command}" />
<Setter Property="CommandParameter" Value="{Binding Path=Parameter}" />
</Style>
It really seems like an ItemTemplate should work, and it would be the better way to go, but this is the only way I've found that actually works properly.
它看起来好像是一个ItemTemplate应该工作,这将是更好的方式,但这是我发现实际上正常工作的唯一方法。