Click here to Skip to main content
11,712,241 members (63,664 online)
Rate this: bad
good
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}">
    <HierarchicalDataTemplate.ItemContainerStyle>
        <Style TargetType="MenuItem">
            <Style.Resources>
                <Image x:Key="ItemImage" Source="{Binding ImageSource}" Width="16" Height="16" x:Shared="false" />
            </Style.Resources>
            <Style.Setters>
                <Setter Property="Command" Value="{Binding Command}" />
                <Setter Property="CommandParameter" Value="{Binding CommandParameter}" />
                <Setter Property="Icon" Value="{StaticResource ItemImage}" />
            </Style.Setters>
        </Style>
    </HierarchicalDataTemplate.ItemContainerStyle>
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Title}" />
    </StackPanel>
</HierarchicalDataTemplate>

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 'http://schemas.microsoft.com/winfx/2006/xaml' 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 0:34am

1 solution

Rate this: bad
good
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;
   }
 
   #endregion
}

Hope this helps,

Regards,

Thomas.
  Permalink  
v2
Comments
Peltchag at 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 at 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
0 CHill60 335
1 Sergey Alexandrovich Kryukov 254
2 OriginalGriff 230
3 Andy Lanng 160
4 Maciej Los 130
0 CHill60 335
1 Sergey Alexandrovich Kryukov 245
2 OriginalGriff 230
3 Andy Lanng 160
4 Maciej Los 130


Advertise | Privacy | Mobile
Web02 | 2.8.150819.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