Question

I am trying to dynamically bind context menus from my base view model. I've managed to functionally do what i'd like to do, but I'm stuck with how my dynamic context menu looks compared to my static one. There seems to be an extra level of menu items. My View Model looks like this.

 public ObservableCollection<ContextMenuItem> ContextMenuItems { get; protected set; }

protected Constructor 
{
     ContextMenuItems = new ObservableCollection<ContextMenuItem>()
                    {
                        new ContextMenuItem() {Caption = "Add/Replace Supporting Data", Command = AddReplaceSupportingCommand},
                        new ContextMenuItem() {Caption = "Display SupportingData", Command = DisplaySupportingDataCommand}
                    };
}

the xaml for the 1st context menu us generated like this.

    <StackPanel Orientation="Vertical" Margin="0,20">
            <StackPanel.ContextMenu >
                <ContextMenu ItemsSource="{Binding ContextMenuItems}">
                    <ContextMenu.ItemTemplate>
                        <DataTemplate>
                            <MenuItem Command="{Binding Command}" Header="{Binding Caption}"/>
                        </DataTemplate>
                    </ContextMenu.ItemTemplate>
                </ContextMenu>
            </StackPanel.ContextMenu>
...

</StackPanel>

The xaml for the second context menu looks like this

<StackPanel >
        <StackPanel.ContextMenu>
            <ContextMenu>
                <MenuItem Command="{Binding AddReplaceSupportingCommand}" Header="Add or Replace Supporting Data"/>
                <MenuItem Command="{Binding DisplaySupportingDataCommand}" Header="Display Supporting Data"/>
            </ContextMenu>
        </StackPanel.ContextMenu>
...
</StackPanel>

(for completeness, here's the ContextMenuItem class)

public class ContextMenuItem : ReactiveObject
    {
        private string _Caption;
        public string Caption
        {
            get { return _Caption; }
            set { this.RaiseAndSetIfChanged(ref _Caption, value); }
        }

        public ReactiveCommand Command { get; set; }
    }

Differences between dynamic and statically generated context menus

Was it helpful?

Solution

It looks different because ContextMenu, MenuBase to be specific, uses MenuItem as ItemContainerStyle so you're effectively wrapping MenuItem within MenuItem. Try this instead:

<StackPanel Orientation="Vertical" Margin="0,20">
    <StackPanel.ContextMenu>
        <ContextMenu ItemsSource="{Binding ContextMenuItems}">
            <ContextMenu.ItemContainerStyle>
                <Style TargetType="{x:Type MenuItem}">
                    <Setter Property="Header" Value="{Binding Caption}"/>
                    <Setter Property="Command" Value="{Binding Command}"/>
                </Style>
            </ContextMenu.ItemContainerStyle>
        </ContextMenu>
    </StackPanel.ContextMenu>
    <!-- ... -->
</StackPanel>

you can use ItemTemplate if you want but use something like TextBox instead

<StackPanel Orientation="Vertical" Margin="0,20">
    <StackPanel.ContextMenu >
        <ContextMenu ItemsSource="{Binding ContextMenuItems}">
            <ContextMenu.ItemContainerStyle>
                <Style TargetType="{x:Type MenuItem}">
                    <Setter Property="Command" Value="{Binding Command}"/>
                </Style>
            </ContextMenu.ItemContainerStyle>
            <ContextMenu.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Caption}"/>
                </DataTemplate>
            </ContextMenu.ItemTemplate>
        </ContextMenu>
    </StackPanel.ContextMenu>
    <!-- ... -->
</StackPanel>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top