Click here to Skip to main content
Click here to Skip to main content

Dynamically Generating Context Menu Items

, 28 May 2014
Rate this:
Please Sign up or sign in to vote.
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

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

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

       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:

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

And the separator Template:

    <DataTemplate x:Key="SeparatorCommandItem" DataType="local:SeparatorCommandItem">
        <Separator />
    </DataTemplate>  
All that is left to do is to implement ContextMenuItemContainerTemplateSelector
    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)

Share

About the Author

Mayur Shah
Technical Lead
India India
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web03 | 2.8.140814.1 | Last Updated 28 May 2014
Article Copyright 2014 by Mayur Shah
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid