Click here to Skip to main content
15,886,806 members
Articles / Desktop Programming / WPF
Tip/Trick

Dynamically Generating Context Menu Items

Rate me:
Please Sign up or sign in to vote.
4.64/5 (6 votes)
28 May 2014CPOL1 min read 29.5K   49   8   2
Article describes how to dynamically generate Context Menu Items, requiring separate templates based on items on the collection

Introduction

Recently I needed to auto generate context menu items bound to command collection in my View Model. and the data template needed to be different based on the type of the item in the list. Article is outcome of what I learned from it.

Background

From the title it sounds like a 30-second task where all you need is to have a collection with different command items and bind it to context menu's ItemsSoruce and use ItemTemplateSelector. I started with the same assumption but solution turned out to be a bit more trickier.

Using the code

Well solution is straight forward. All you need it to remember to use ItemContainerTemplateSelector. But that is not all, you will also need to set property UsesItemContainerTemplate in order for your template selector to be effective.

A very basic example to illustrate is attached:
In the example, ContextMenu is bound to property ContextItems

XML
<ContextMenu ItemsSource="{Binding Path=ContextItems}" UsesItemContainerTemplate="True"  ItemContainerTemplateSelector="{StaticResource _templateSelector}" />

ContextItems is collection of ICommandItem which contains properties like Text (header), ToolTip and Command.

C#
ContextItems = new List<ICommandItem>(){
  new SimpleCommandItem() { Text ="Simple Command 1", ToolTip="Simple Tooltip 1"},
  new SeparatorCommandItem(),
  new SimpleCommandItem() { Text ="Simple Command 2", ToolTip="Simple Tooltip 2"}

SimpleCommandItem class is implementation for the interface.
SeparatorCommandItem implements the interface explicitly but throws exceptions on implementation (for obvious reasons!).

ContextMenuResources.xaml is resource dictionary that holds data templates for both the classes.

SimpleCommandItem Template:

XML
<DataTemplate x:Key="SimpleCommandItem" DataType="local:SimpleCommandItem">
    <MenuItem Header="{Binding Path=Text}" ToolTip="{Binding Path=ToolTip}" Command="{Binding Command}" />
</DataTemplate>

And the separator Template:

XML
<DataTemplate x:Key="SeparatorCommandItem" DataType="local:SeparatorCommandItem">
    <Separator />
</DataTemplate>
All that is left to do is to implement ContextMenuItemContainerTemplateSelector
C#
public class ContextMenuItemContainerTemplateSelector : ItemContainerTemplateSelector
{
    private static ResourceDictionary _dictionary;
    static ContextMenuItemContainerTemplateSelector()
    {
        _dictionary = new ResourceDictionary();
        _dictionary.Source = new Uri(@"pack://application:,,,/ContextMenu.Framework;component/ContextMenuResources.xaml");
    }
    public override DataTemplate SelectTemplate(object item, ItemsControl parentItemsControl)
    {
        var name = item == null ? null : item.GetType().Name;
        if (name != null && _dictionary.Contains(name))
        {
            return (DataTemplate)_dictionary[name];
        }
        return null;
    }
}
History

Keep a running update of any changes or improvements you've made here.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionAssumed Knowledge Pin
Member 1081219124-Jun-15 3:26
Member 1081219124-Jun-15 3:26 
QuestionCommand and CommandParameter Pin
Anoebis9-Apr-15 23:52
Anoebis9-Apr-15 23:52 
Hi,

I would like to call a command that takes a parameter, so extend ICommand. Also what is the interface definition of ICOmmand, especially Command, is it passed by name or as ICommand or am I missing something completely?
I'm getting the context menu visible, only need to add the actions.
An example project would help.

Thanks for the article.

Marco
Marco

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.