Click here to Skip to main content
15,891,136 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
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 :

XML
<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
Comments
jvan filizzola 9-Mar-20 6:50am    
sorry can i ask you the code? I have problem with bind a structure hierarchical with a menu :(

1 solution

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)
XML
<local:menuiconconverter x:key="menuIconConverter" xmlns:x="#unknown" xmlns:local="#unknown" />


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


And in the namespace referenced by local, this class:
C#
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.
 
Share this answer
 
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)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900