Click here to Skip to main content
11,926,961 members (53,715 online)
Rate this:
Please Sign up or sign in to vote.
See more: WPF menu DataTemplate image , +
In a WPF client application, I'm having some difficulties using hierarchical data template to load databound menuitems.

First I created the ViewModel, containing the basic properties for a menu item : Title, Command, ImageSource (Path to the image to use for Icon property) and sub items.

Then, I created the view in a XAML window to display my menus. To bind my collection, taking sub items into account, I used the hierarchical data template for the menu item template.

Here is the XAML code for the ItemTemplate :

<HierarchicalDataTemplate DataType="{x:Type vm:MenuItemViewModel}" ItemsSource="{Binding Path=Items}">
        <Style TargetType="MenuItem">
                <Image x:Key="ItemImage" Source="{Binding ImageSource}" Width="16" Height="16" x:Shared="false" />
                <Setter Property="Command" Value="{Binding Command}" />
                <Setter Property="CommandParameter" Value="{Binding CommandParameter}" />
                <Setter Property="Icon" Value="{StaticResource ItemImage}" />
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Title}" />

When I initialize the menus and show the window, all looks fine.

After that, I tried to put the menu item template into a resource dictionary in order to be able to reuse it from wherever in my application as a default template.
When I do that, I have an exception thrown :
Shared attribute in namespace '' can be used only in compiled resource dictionaries.

After spending so much time searching for a solution, I finally made a tester project (available here) to demonstrate the problem.

I don't know how to make my resource dictionary being a compiled resource dictionary...
Could anyone help me ?
Posted 10-Sep-12 1:34am

1 solution

Rate this: bad
Please Sign up or sign in to vote.

Solution 1

Hi Peltchag,

I had the same problem and AFAIK this isn't possible for resource dictionaries.

What I ended up with is using a ValueConverter in my DataTemplate.

Make the converter accessible (where local is an alias for the namespace)
<local:menuiconconverter x:key="menuIconConverter" xmlns:x="#unknown" xmlns:local="#unknown" />

And then write in your DataTemplate something like:
<setter property="Icon" value="{Binding ImageSource, Converter={StaticResource menuIconConverter}}" />

And in the namespace referenced by local, this class:
using System;
using System.Globalization;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media.Imaging;
[ValueConversion(typeof(String), typeof(Image))]
public class MenuIconConverter : IValueConverter
   #region IValueConverter implementation

   public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
      if (value == null)
         return Binding.DoNothing;
      string imageUrl = value.ToString();
      if (string.IsNullOrEmpty(imageUrl))
         return Binding.DoNothing;

      var bmp = new BitmapImage(new Uri(imageUrl, UriKind.RelativeOrAbsolute)) { DecodePixelHeight = 16, DecodePixelWidth = 16 };
      return new Image { Width = 16, Height = 16, Source = bmp, UseLayoutRounding = true, SnapsToDevicePixels = true };
   public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
      return Binding.DoNothing;

Hope this helps,


Peltchag 10-Sep-12 8:28am
This solution work fine.
I was expecting not to write code behind to solve this, but if it's the only way... :)

Thanks for your help !
Thomas Duwe 10-Sep-12 8:40am
Yeah, I too was against code behind in this case, but I found no other way :-(

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

  Print Answers RSS
Top Experts
Last 24hrsThis month

Advertise | Privacy | Mobile
Web01 | 2.8.151126.1 | Last Updated 10 Sep 2012
Copyright © CodeProject, 1999-2015
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100