Three Ways To Create Dynamic Menus

There are quite a few sources about how to create dynamic menus (menus that are not embedded in XAML or code, but rather loaded from an external file):

  1. Loose XAML – Using the XamlReader, one can load an external, non-pre-compiled fragment of XAML, much like the one presented here:
    <MenuItem Header="1" />
    <MenuItem Header="2" />
    <MenuItem Header="3" />

    The above fragment will then be loaded into the menu like so:

    using (FileStream looseXamlFile = File.OpenRead("Loose.xaml"))

    And on the window, it will look like this:


    This is a very useful thing and you can read more about this method on Tamir’s weblog.
    However, this way, you are bound to the elements of the WPF schema and all errors that would have occurred in the past during compile-time, will now occur during run-time. These presents a hardship for the developer. The bigger problem is what happens when receiving the items for the menu from a different source, such as a list you wish to bind to, in which case, you simply can’t use Loose XAML.

  2. Data Templates – This way is the most intuitive way to bind a list of items or, better yet, an unary tree of items to a GUI representation of them. For instance, we have a list of Item objects (a simple class with one property – Value) and wish to bind them to menu items.
    <MenuItem x:Name="dataTemplateMenu" Header="_Data Template" >
    <DataTemplate DataType="{x:Type local:Item}">
    <MenuItem Header="{Binding Path=Value}" />

    The XAML described here takes each Item and represents it using a MenuItem. To load a list into the menu, we simply call:

    dataTemplateMenu.ItemsSource = itemArray;

    After this call, all of the items will have MenuItems created for them and will look like this:


    Very nice, but something is wrong here. Yes, the items are extremely large. Hovering over one reveals that we have something inside that menu:


    Hum. That looks familiar. It’s the same size as a normal MenuItem… Oh, wait, that’s because it really is one. This is because when you create a Data Template, the items that enter the tree are actually your user-defined objects (in this case, the Item class). Before applying the template, the menu item asks the object about to be inserted into it whether it can be visually displayed. Because Item has no visual representation, the process creates a MenuItem to hold it, thus creating two menu items (the one automatically created and the one created using the Data Template).

  3. Item Container Style – So after two ways that didn’t work well for us, the one that will is the MenuItem’s ItemContainerStyle. This way, all you do is simply define a style for all of the menu items that will be placed under a certain menu item and use binding to bind those items to the values of your objects’ properties:
    <MenuItem x:Name="itemContainerStyleMenu" Header="_Item Container Style">
    <Style TargetType="{x:Type MenuItem}">
    <Setter Property="Header" Value="{Binding Path=Value}" />

    Then you set the source:

    itemContainerStyleMenu.ItemsSource = itemArray;

    and presto:

    We now have what we needed.

    Extra: Recursive hierarchy could also be achieved using:

    1. Placing the style in the resources of a window, the application, etc. with a key.
    2. A setter of ItemsSource that binds to the collection of child items.
    3. A setter of ItemContainerStyle that will point to the style’s key.

The source for this article is available here.

Pet peeve: Why would you change the “&Name” mnemonic notation from Win32 to something that is not better (“_Name” in WPF), only different? I’d have gone with a MenuItem.Mnemonic property that receives a character and doesn’t pass validation if the Text property doesn’t contain that character. If you’re going to change, you might as well change for a reason.


13 thoughts on “Three Ways To Create Dynamic Menus

  1. I thought the change from &Name to _Name mnemonic notation was obvious. Have you ever tried to write lots of ampersands in attributes of Xml? It’s a pain in the proverbial.

  2. I’m glad to see the & to _ switch, for the simple reason that & is sometimes used as a literal character in captions, whereas _ is not.

  3. Replacing & by _ is quite understadable : if they had kept the & mnenonic, your xaml would have looked like :
    Header=”&Item Container Style”
    which is not nice

  4. Is there a way that I can directly add the menu items to the collection of menu items of the menu. Like MainMenu.Items.Add(menuItem);

  5. I know this is kind of an old post and you might’ve addressed this elsewhere, but someone just pointed me to this post. You can use a DataTemplate such as the following:

    A MenuItem will be created and wrapped around the TextBlock.

  6. What happens if you want to dynamically bind an image as well? This doesn’t work;

    I’ve found one post that suggested re-templating the control.
    Seems like overkill, I just did something like this instead;
    foreach (IEntitySearchView view in Data.SearchViews)
    myControl.ContextMenu.Items.Add(new MenuItem()
    Header = view.DisplayName,
    Command = SelectViewCommand,
    CommandParameter = view,
    Icon = new Image() { Source = new BitmapImage(new Uri(view.IconURI)), Height = 16, Width = 16 }

  7. I try to create a dynamic menu, but it doesn’t see the style. The MenuItems appear with an inner menuitem (see commented section).
    Can you help?


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s