views:

337

answers:

1

I have a tree of ViewModels displayed as a TreeView (using HierarchicalDataTemplate). Each ViewModel instance has different commands that can be executed on it wich again are exposed as a list of command ViewModels for each item ViewModel. How can I create a single ContextMenu that opens at the TreeViewItem that was rightclicked and that populates its commands from the underlying item ViewModel's command ViewModels list? All in a decent MVVM fashion ...

A: 

I think I understand your question. I think that you could structure your ViewModels like this:

interface ICommandViewModel : ICommand
{
  string Name {get;}
}

interface INodeViewModel
{
  IEnumerable<ICommandViewModel> CommandList {get;}
}

public class NodeViewModel : INodeViewModel
{
  public NodeViewModel()
  {
    //Init commandList
    //Populate commandList here(you could also do lazy loading)
  }

  public NodeViewModel(IEnumerable<ICommandViewModel> commands)
  {
    CommandList = commands;
  }

  public IEnumerable<ICommandViewModel> CommandList {get;private set;}
}

and then in xaml

<TreeViewItem>
  <TreeViewItem.ContextMenu Items={Binding CommandList}>
    <ContextMenu.ItemTemplate>
      <DataTemplate>
        <MenuItem Header="{Binding Name}" Command="{Binding}"/>
      </DataTemplate>
    </ContextMenu.ItemTemplate>
  </TreeViewItem.ContextMenu>
</TreeViewItem>

I don't have much experience with hierarchical datatemplate but you get the gist from the above. You could also do the above with a style in the but I don't have a xaml editor in front of me to give you right syntax.

Hope that helps

Jose
When I have a hughe tree with lots of items wouldn't that create thousands of contextmenus? Wouldn't that be a problem? I need just one context menu that changes its content based on the current item.
bitbonk
Personally, I wouldn't worry about it unless you notice a perfomance hit. I doubt it would. But another choice is to have an IEnumerable<ICommand> in your TreeView ViewModel which is dynamically populated with the Selected NodeViewModel. But then you need to store which one's selected so you can populate it's ICommands. I don't think the complexity is worth it.
Jose
I don't know the memory foot print for one MenuItem control, but let's say it's 1KB(which is probably high) a thousand of those would only be 1MB. I don't think you should worry about it. Plus WPF probably lazy loads the MenuItems anyway, so probably only the nodes that get right-clicked will take memory.
Jose