Search code examples
c#wpfbindingmenuitemitemssource

Trouble binding WPF Menu to ItemsSource


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):

alt text

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):

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

So, the menu is bound to a collection of ICommands, and each item's CommandParameter is set to the same global target (which happens to be a collection, but that's not important).

My question is, is there any way I can bind this such that WPF doesn't automatically wrap each item in a MenuItem?


Solution

  • I would be inclined to subclass ContextMenu and override 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.

    This presumes you can't simply use ItemContainerStyle on a regular MenuItem to get the effect you want:

    <ContextMenu ...>
      <ContextMenu.ItemContainerStyle>
        <Style>
          ...
        </Style>
      </ContextMenu.ItemContainerStyle>
    </ContextMenu>