Add icon to HierarchicalDataTemplate

7 posts, 1 answers
  1. Charles
    Charles avatar
    75 posts
    Member since:
    Aug 2008

    Posted 03 Feb 2009 Link to this post

    I'm creating a menu at runtime using an ObservableCollection. I load up this collection when the application first loads something like this:
            private void LoadMenu()  
            {  
                BitmapImage bi = null;  
     
                /* Load menu items and the associated UserControls */  
                menuDataItems = new ObservableCollection<MenuDataItem>();  
                MenuDataItem validationLevel = new MenuDataItem() {Name = "Validation"NextPage = null};  
                MenuDataItem rulesLevel = new MenuDataItem() { Name = "Rules"NextPage = null };  
                MenuDataItem helpLevel = new MenuDataItem() { Name = "Help"NextPage = null };  
                bi = new BitmapImage(new Uri("../Common/images/task.png", UriKind.Relative));  
                MenuDataItem validItem = new MenuDataItem()  
                                             {  
                                                 Name = "Validate"NextPage = typeof(ValidationView),  
                                                 Icon = new Image()  
                                                                 {  
                                                                     Height = 16,  
                                                                     Width = 16,  
                                                                     Source = bi 
                                                                 }  
                                             };  
                validationLevel.Add(validItem);  
     
                MenuDataItem ruleItem = new MenuDataItem() { Name = "View Rules"NextPage = typeof(RulesView) };  
                rulesLevel.Add(ruleItem);  
                ruleItem = new MenuDataItem() { Name = "New Rule"NextPage = null };  
                rulesLevel.Add(ruleItem);  
     
                MenuDataItem helpItem = new MenuDataItem() { Name = "About"NextPage = null };  
                helpLevel.Add(helpItem);  
     
                menuDataItems.Add(validationLevel);  
                menuDataItems.Add(rulesLevel);  
                menuDataItems.Add(helpLevel);  
                mnuMain.ItemsSource = menuDataItems;  
            } 
    So, I have an image defined to be used in certain menu items. In the XAML - I have a HierarchicalDataTemplate set up this way:
            <telerik:RadMenu Grid.Row="1" x:Name="mnuMain" HorizontalAlignment="Stretch" VerticalAlignment="Top">  
                <telerik:RadMenu.ItemTemplate> 
                    <core:HierarchicalDataTemplate ItemsSource="{Binding}">  
                        <TextBlock Text="{Binding Name}"/>  
                    </core:HierarchicalDataTemplate> 
                </telerik:RadMenu.ItemTemplate> 
            </telerik:RadMenu> 
    My question is - how do I add an element to the HierarchicalDataTemplate that will be able to access the image that is part of the binding to the control? Or - is there another way to accomplish this?
  2. Hristo
    Admin
    Hristo avatar
    832 posts

    Posted 05 Feb 2009 Link to this post

    Hello Charles,

    You can have more then one element in the HierarchicalDataTemplate like:
    <telerik:RadMenu Grid.Row="1" x:Name="mnuMain" HorizontalAlignment="Stretch" VerticalAlignment="Top">     
        <telerik:RadMenu.ItemTemplate>    
            <core:HierarchicalDataTemplate ItemsSource="{Binding}">  
                 <StackPanel Orientation="Horizontal">  
                    <Image Source="{Binding ImagePath}"/>  
                    <TextBlock Text="{Binding Name}"/>  
                 </StackPanel>     
            </core:HierarchicalDataTemplate>    
        </telerik:RadMenu.ItemTemplate>    
    </telerik:RadMenu>    
     

    I've added StackPanel and in this stackpanel I've added Image control. Source property of the image control is bound to ImagePath property (this should be property of your data item. The type can be string and you should add UriTypeConverter attribute to this property).

    Let me know if you need more help.

    Best wishes,
    Hristo
    the Telerik team

    Check out Telerik Trainer, the state of the art learning tool for Telerik products.
  3. DevCraft banner
  4. Charles
    Charles avatar
    75 posts
    Member since:
    Aug 2008

    Posted 05 Feb 2009 Link to this post

    Sorry, I wasn't as clear as I should have been.

    Although the suggestion you gave does allow me to add an image to the menu item, it is not in the area I would have expected. It is instead right up against the text for the menu item - and there is a space (reserved for an image I think) to the left of that.

    So, I think what I need to do is populate the Icon property of certain menu items dynamically. I was hoping I could use the HierarchicalDataTemplate to do that.

    For instance, I have on the top level of the menu an item with the text of "Validation". Under that, as a child item, is an item with the text "Validate". I would like to put the image there, but I think I need to put it in the Icon property.

    Is there any way to do that using the HierarchacalDataTemplate? If not - do you have any other suggestions regarding dynamically and selectively setting the Icon property in certain menu items.

    Thanks.
  5. Hristo
    Admin
    Hristo avatar
    832 posts

    Posted 06 Feb 2009 Link to this post

    Hello Charles,

    In a perfect world (read WPF) what you try to achieve is to bind the container (RadMenuItem) Icon property to the dataItem Icon property. This can be achieved using the ItemContainerStyle property. Unfortunately in Silverlight 2 you are not allowed to set binding in style setters. So this is not possible.
    As a workaround you could inherit from RadMenuItem and add this binding from code.
    You can read more from here:
    http://www.telerik.com/community/forums/silverlight/menu/radmenu-and-hierarchicaldatatemplate.aspx

    Let me know if you need more help.

    Regards,
    Hristo
    the Telerik team

    Check out Telerik Trainer, the state of the art learning tool for Telerik products.
  6. Charles
    Charles avatar
    75 posts
    Member since:
    Aug 2008

    Posted 06 Feb 2009 Link to this post

    Hristo

    I've just implemented the suggestion in the other thread you referenced. Thank you for that. I think I'm still doing something wrong, though.

    I am creating a BitmapImage and stroring that in the Icon property of my MenuDataItem (custom item loaded at runtime into an ObservableCollection and bound to the menu). That might be my first mistake. All I get in the menu icon area is the name of the BitmapImage object - not the actual bitmap. Here is a snippet of the code that creates the BitmapImage:

                BitmapImage img;  
                img = new BitmapImage(new Uri("../Common/images/task.png", UriKind.Relative));  
                MenuDataItem validItem = new MenuDataItem()  
                                             {  
                                                 Name = "Validate",  
                                                 NextPage = typeof (ValidationView),  
                                                 Icon = img 
                                             }; 

    Now, the first question is....should I be using some other type to create the icon? Another question is...is there some additional binding I need to add to the HierarchicalDataTemplate. Here is what I am doing in the XAML.

            <localControl:RadMenuExtended Grid.Row="1" x:Name="mnuMain" HorizontalAlignment="Stretch" VerticalAlignment="Top">  
                <localControl:RadMenuExtended.ItemTemplate> 
                    <core:HierarchicalDataTemplate ItemsSource="{Binding}">  
                        <StackPanel Orientation="Horizontal">  
                            <TextBlock Text="{Binding Name}"/>  
                        </StackPanel> 
                    </core:HierarchicalDataTemplate> 
                </localControl:RadMenuExtended.ItemTemplate> 
            </localControl:RadMenuExtended> 

    Finally, here is the code for the RadMenuExtended and RadMenuItemExtended. It is pretty much the same as the sample you had provided in the other thread with the exception of using the Icon property instead of IsEnabled.

        public class RadMenuExtended : RadMenu  
        {  
            protected override bool IsItemItsOwnContainerOverride(object item)  
            {  
                return (item is RadMenuItemExtended);  
            }  
     
            protected override System.Windows.DependencyObject GetContainerForItemOverride()  
            {  
                return new RadMenuItemExtended();  
            }     
              
            protected override void PrepareContainerForItemOverride(DependencyObject element, object item)  
            {  
                base.PrepareContainerForItemOverride(element, item);  
                RadMenuItem menuItem = element as RadMenuItem;  
     
                if(!object.ReferenceEquals(menuItem, item))  
                {  
                    Binding binding = new Binding("Icon");  
                    binding.Source = item;  
                    menuItem.SetBinding(RadMenuItem.IconProperty, binding);  
                }  
            }  
        }  
     
        public class RadMenuItemExtended : RadMenuItem  
        {  
            protected override bool IsItemItsOwnContainerOverride(object item)  
            {  
                return (item is RadMenuItemExtended);  
            }  
     
            protected override System.Windows.DependencyObject GetContainerForItemOverride()  
            {  
                return new RadMenuItemExtended();  
            }  
     
            protected override void PrepareContainerForItemOverride(System.Windows.DependencyObject element, object item)  
            {  
                base.PrepareContainerForItemOverride(element, item);  
     
                RadMenuItem menuItem = element as RadMenuItem;  
     
                if (!object.ReferenceEquals(menuItem, item))  
                {  
                    Binding binding = new Binding("Icon");  
                    binding.Source = item;  
                    menuItem.SetBinding(RadMenuItem.IconProperty, binding);  
                }  
            }     
              
        } 
  7. Answer
    Hristo
    Admin
    Hristo avatar
    832 posts

    Posted 06 Feb 2009 Link to this post

    Hello Charles,

    You should use Image control not the BitmapImage. You don't need more bindings in HierarchicalDataTemplate.

    One small note - there is an improved version that I've attached in my last post. It has some more validations (mainly if the container is RadMenuItem not RadSeparator) and allows you to put RadSeparator in your datasource collection. I recommend to use it.

    (http://www.telerik.com/ClientsFiles/114643_page27.zip)

    Regards,

    Hristo
    the Telerik team

    Check out Telerik Trainer, the state of the art learning tool for Telerik products.
  8. Charles
    Charles avatar
    75 posts
    Member since:
    Aug 2008

    Posted 06 Feb 2009 Link to this post

    Hristo

     

    Thanks very much. That did it. I didn't use your new suggested code yet, but I will upgrade to that shortly.

Back to Top
DevCraft banner