Click here to Skip to main content
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 1: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 OriginalGriff 7,903
1 Sergey Alexandrovich Kryukov 7,142
2 DamithSL 5,604
3 Manas Bhardwaj 4,986
4 Maciej Los 4,820


Advertise | Privacy | Mobile
Web02 | 2.8.1411023.1 | Last Updated 10 Sep 2012
Copyright © CodeProject, 1999-2014
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