问题
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.
The problem that I'm having is that if a MenuItem has children, it's command doesn't get exectuted. Any Item that has no children, the Command is exectured without issue.
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
}
Here's the way a context item is actually used.
MenuItems = new List<IContextMenuItem>
{
new BasicContextMenuItem("New Folder") { Command = NewFolderCommand} ,
new BasicContextMenuItem("Delete Folder") { Command = DeleteFolderCommand },
new BasicContextMenuItem("Rename") { Command = RenameFolderCommand },
};
public ICommand NewFolderCommand
{
get { return new RelayCommand<FolderViewModel>(NewFolder); }
}
private void NewFolder(FolderViewModel viewModel)
{
// Do work
}
回答1:
I see the problem is with XAML binding. What you need is HierarchicalDataTemplate
binding. The code doesn't bind the command for the children which I believe is causing the issue.
Check if this helps - Command binding not working in a dynamic MVVM Context Menu
来源:https://stackoverflow.com/questions/19557182/wpf-menuitem-with-children-not-firing-bound-command