Click here to Skip to main content
12,946,783 members (49,353 online)
Rate this:
 
Please Sign up or sign in to vote.
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 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
OriginalGriff 5,059
CHill60 3,235
Maciej Los 2,538
Jochen Arndt 1,935
ppolymorphe 1,795


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