3

我想通过绑定到ICommand衍生对象列表来避免必须在 XAML 或代码中手动构建菜单。但是,我遇到了一些问题,其中生成的菜单有两个级别的菜单项(即每个MenuItem都包含在 a 中MenuItem):

替代文字

我的猜测是,这是因为 WPF 会自动MenuItem为我的绑定生成 a,但实际上我使用的“查看器”已经a 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>

(ItemContainerStyleSelector 来自http://bea.stollnitz.com/blog/?p=23,它允许我Separator在绑定源中包含元素。)

因此,菜单绑定到ICommands 的集合,并且每个项目CommandParameter都设置为相同的全局目标(恰好是一个集合,但这并不重要)。

我的问题是,有什么方法可以绑定它,以使 WPF 不会自动将每个项目包装在MenuItem?

4

2 回答 2

3

不幸的是,我发现解决此问题的最佳方法是使用 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>

看起来 ItemTemplate 确实应该工作,这将是更好的方法,但这是我发现实际工作正常的唯一方法。

于 2010-06-11T16:59:15.420 回答
2

我倾向于继承 ContextMenu 并覆盖 GetContainerForItemOverride:

public class ContextMenuWithNoteCommands : ContextMenu
{
  protected virtual DependencyObject GetContainerForItemOverride()
  {
    return new NoteCommandMenuItemViewer();
  }
}

然后在 NoteCommandMenuItemViewer 样式或 ContextMenu.ItemContainerStyle 中设置 CommandParameter 绑定,以更合适的方式设置。

这假定您不能简单地在常规 MenuItem 上使用 ItemContainerStyle 来获得您想要的效果:

<ContextMenu ...>
  <ContextMenu.ItemContainerStyle>
    <Style>
      ...
    </Style>
  </ContextMenu.ItemContainerStyle>
</ContextMenu>
于 2010-06-11T18:06:41.423 回答