none
WPF - MenuItem with children not firing bound command RRS feed

  • Question

  • So I've been butting my head against the wall with this one all day.

    In my WPF application (using MVVM Light), I have a context menu which is bound to a collection of viewmodels, and it is not behaving quite correctly. I can create my menu, and everything works perfectly with my tree of MenuItems behaving, commands being executed, and the correct parameter coming through. I'm using this to make a context menu which allows a user to add items to folders.

    The problem that I've run into is that when a context menu item has children, the command is no longer fired. Thusly, I can only add items to folders which have no child folders.

    I've investigated this using Snoop, and my DataContext is showing up correctly for the MenuItem, and the command is bound correctly, and the mousedown event does get fired.

    Does anyone know of a way to get commands to fire on MenuItems that have children? I'm really at a loss here, and every similar question on Stack Overflow or MSDN social remains unanswered.

    I've set up my bindings in a style.

    <utility:DataContextSpy x:Key="Spy" />
    
    <!-- Context style (in UserControl.Resources) -->
    
    <Style x:Key="ContextMenuItemStyle" TargetType="{x:Type MenuItem}">
    
        <Setter Property="Header" Value="{Binding Header}"/>
        <Setter Property="ItemsSource" Value="{Binding Children}"/>
         <Setter Property="Command" Value="{Binding Command}" />
         <Setter Property="CommandParameter" Value="{Binding DataContext, Source={StaticResource Spy}}" />
         <Setter Property="CommandTarget" Value="{Binding Path=PlacementTarget, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
    </Style>
    
    <!-- Later in the control -->
     <ContextMenu ItemContainerStyle="{StaticResource ContextMenuItemStyle}" ItemsSource="{Binding MenuItems}" />

    Note that the DataSpy comes from this article, and works as described to allow me to use the datacontext of my usedcontrol as a command parameter 

    http://www.codeproject.com/Articles/27432/Artificial-Inheritance-Contexts-in-WPF

    Here is the viewmodel used for the context menu

    public interface IContextMenuItem
        {
            string Header { get; }
            IEnumerable<IContextMenuItem> Children { get; }
            ICommand Command { get; set; }
        }
    
        public class BasicContextMenuItem : ViewModelBase, IContextMenuItem
        {
            #region Declarations
    
            private string _header;
            private IEnumerable<IContextMenuItem> _children;
    
            #endregion
    
            #region Constructor
    
            public BasicContextMenuItem(string header)
            {
                Header = header;
                Children = new List<IContextMenuItem>();
            }
    
            #endregion
    
            #region Observables
    
            public string Header
            {
                get { return _header; }
                set
                {
                    _header = value;
                    RaisePropertyChanged("Header");
                }
            }
    
            public IEnumerable<IContextMenuItem> Children
            {
                get { return _children; }
                set
                {
                    _children = value;
                    RaisePropertyChanged("Children");
                }
            }
    
            public ICommand Command { get; set; }
    
            #endregion
        }


    Thursday, October 24, 2013 4:41 AM

Answers

  • Hi,

    Its not working because you do not set your Style to every MenuItem. You only set the Style on those MenuItem which are at top most level of ContextMenu.

    This piece of code sets only Style to containers but not containers of containers.

    <ContextMenu ItemContainerStyle="{StaticResource ContextMenuItemStyle}".....

    If you remove the key from your Style and only let the Style be applied to every MenuItem it will work for every MenuItem. (No matter if its a child of another MenuItem)

    Like this:

    <Style TargetType="{x:Type MenuItem}"> <Setter..... />

    Now each MenuItem no matter if a child of another MenuItem will have the Commands and Headers available for Binding.

    If you wish to read more about ContextMenus in WPF, check this link out:

    http://msdn.microsoft.com/en-us/library/ms742558.aspx

    http://wpftutorial.net/ContextMenu.html



    Thursday, October 24, 2013 6:55 AM