Binding "RadMenuItem.Icon" and "RadMenuItem.Header" properties to element in a hierarchical data structure....

10 posts, 1 answers
  1. Rob
    Rob avatar
    238 posts
    Member since:
    Jan 2009

    Posted 15 Apr 2009 Link to this post

    I am having problems binding a RadMenu to my hierarchical data object.

    Here is my UserControl consisting of a simple RadMenu and two item templates, one which displays items in red and the other in blue:

    <

    UserControl x:Class="SilverlightApplication32.Page2" xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:rad="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls" xmlns:radnav="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Navigation" xmlns:local="clr-namespace:SilverlightApplication32" Width="400" Height="300">

     

     

     

      <UserControl.Resources>

     

     

     

       <rad:HierarchicalDataTemplate x:Key="itemTemplate" ItemsSource="{Binding Items}">

     

     

     

         <!--<TextBlock Text="{Binding Caption}" Foreground="Blue" />-->

     

     

     

         <radnav:RadMenuItem Header="{Binding Caption}" Foreground="Blue" Icon="{Binding Image}" />

     

     

     

       </rad:HierarchicalDataTemplate>

     

     

     

       <rad:HierarchicalDataTemplate x:Key="itemTemplate2" ItemsSource="{Binding Items}">

     

     

     

         <!--<TextBlock Text="{Binding Caption}" Foreground="Red" />-->

     

     

     

         <radnav:RadMenuItem Header="{Binding Caption}" Foreground="Red" Icon="{Binding Image}" />

     

     

     

       </rad:HierarchicalDataTemplate>

     

     

     

       <local:TemplateSelector x:Key="DataTemplateSelector" />

     

     

     

    </UserControl.Resources>

     

     

     

    <Grid x:Name="LayoutRoot" Background="White">

     

     

     

       <radnav:RadMenu x:Name="radMenu">

     

     

     

         <radnav:RadMenuItem x:Name="RootItem" Header="Root" ItemTemplateSelector="{StaticResource DataTemplateSelector}"/>

     

     

     

       </radnav:RadMenu>

     

     

     

    </Grid>

     

     

     

    </UserControl>

     

     

     

     

     



    Here is my data object that I am tryign to bind with and my code:

     

    public partial class Page2 : UserControl

     

     

    {

     

      public Page2()

     

      {

        InitializeComponent();

     

     

        MenuOption itemA = new MenuOption("A");

     

     

     

        MenuOption itemB = new MenuOption("B");

     

     

     

     

        MenuOption item1 = new MenuOption("1");

     

     

     

        MenuOption item2 = new MenuOption("2");

     

     

     

        MenuOption item3 = new MenuOption("3");

     

     

     

        MenuOption item4 = new MenuOption("4");

     

     

     

        MenuOption item5 = new MenuOption("5");

     

     

     

        MenuOption item6 = new MenuOption("6");

     

     

     

     

        MenuOption itemred = new MenuOption("red");

     

     

     

        MenuOption itemblue = new MenuOption("blue");

     

     

     

        MenuOption itemgreen = new MenuOption("green");

     

     

     

        MenuOption itemorange = new MenuOption("orange");

     

     

     

        MenuOption itempink = new MenuOption("pink");

     

        itemA.Items.Add(item1);

        itemA.Items.Add(item2);

        itemA.Items.Add(item3);

        itemB.Items.Add(item4);

        itemB.Items.Add(item5);

        itemB.Items.Add(

     

    new RadSeparator());

     

        itemB.Items.Add(item6);

        item1.Items.Add(itemred);

        item2.Items.Add(itemblue);

        item3.Items.Add(itemgreen);

        item4.Items.Add(itemorange);

        item5.Items.Add(itempink);

     

     

     

        ObservableCollection<object> source = new ObservableCollection<object>();

     

        source.Add(itemA);

        source.Add(itemB);

        RootItem.ItemsSource = source;

      }

     

    }

     

     

     

    public class TemplateSelector : DataTemplateSelector

     

     

    {

     

      public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)

     

      {

     

     

        if (object.ReferenceEquals(item, container))

     

     

     

          return null;

     

     

     

        return (item as MenuOption).IsSpecial ? (Application.Current.RootVisual as Page2).Resources["itemTemplate"] as HierarchicalDataTemplate : (Application.Current.RootVisual as Page2).Resources["itemTemplate2"] as HierarchicalDataTemplate;

     

      }

    }

     

     

     

    public class MenuOption

     

     

    {

     

      public string Caption { get; set; }

     

     

     

      public FrameworkElement Image { get; set; }

     

     

     

      public bool IsSpecial { get; set; }

     

     

     

      public ObservableCollection<object> Items { get; set; }

     

     

     

     

      public MenuOption(string caption)

     

      {

     

     

        this.Caption = caption;

     

     

     

        this.IsSpecial = (caption.Equals("5") || caption.Equals("A") ? true : false);

     

     

     

        this.Image = new Rectangle() { Fill = new SolidColorBrush(Colors.Orange), Height = 16, Width = 16 };

     

     

     

        this.Items = new ObservableCollection<object>();

     

      }

    }

     

    My problem is simple.... if you run this project you'll see that I have RadMenuItem's inside my RadMenuItem's which isn't what I want.  I would like to have a proper RadMenuItem with a Icon and Header property (not inside another item).... What am I missing here?  I have been driving myself crazy over this and it's probably just something simple.  Another pair of eyes is greatly appreciated.

  2. Boyan
    Admin
    Boyan avatar
    758 posts

    Posted 21 Apr 2009 Link to this post

    Hi Rob,

     Sorry for the late answer. I checked your application and when i run it I can't see nothing wrong with it. All items have icons (orange rectangle in your case)  and the items that you set  "IsSpecial  = true"  are blue.

    Could you please explain more briefly what are you trying to achieve. By what you have written I think that you don't want to have child Items of your MenuItems, but I can't understand what are you trying to achieve.

    Best wishes,
    Boyan
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Check out the tips for optimizing your support resource searches.
  3. DevCraft banner
  4. Rob
    Rob avatar
    238 posts
    Member since:
    Jan 2009

    Posted 21 Apr 2009 Link to this post

    Hi again.

    I've put an image on my site explaining what I'm trying to do.... "A" is what I have now.  "B" is what I am trying to achieve.
    http://www.robertstraume.com/RadMenu.jpg

    Thanks in advance,
    Rob
  5. Hristo
    Admin
    Hristo avatar
    832 posts

    Posted 22 Apr 2009 Link to this post

    Hi Rob,

    What you need is ability to Bind the container (RadMenuItem) to the data item (MenuOption). Silverlight 2 do not support Binding in Style setters so we have created something similar to fill the gap until this is supported. We called it ContainerBindings. It is an attached property that contains Bindings which are applied to all containers.
    I have modified your example a little bit in order to achieve what you need.
    You can find it in the attachments.

    Let us know if you need more information.

    Sincerely yours,
    Hristo
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Check out the tips for optimizing your support resource searches.
  6. Rob
    Rob avatar
    238 posts
    Member since:
    Jan 2009

    Posted 22 Apr 2009 Link to this post

    Awesome!!!  Thanks Hristo, it is working great.  Sorry to be a pain, but another question.  I hope this is the last...

    I noticed that you cannot include RadSeparator's, so I have changed things up a little to try and make it "appear" like there is a separator.

    I used a TemplateSelector at the root level and returned either the HierarchicalDataTemplate (with the ContainerBinding) or another template which simply 'draws' a rectangle to look like a separator based on the MenuOption.IsSeparator property that I created.

    Can you think of a way that I can disable the RadMenuItem when IsSeparator = true thus making it appear to be a separator and not just another item?  I guess the alternative is to go without separators for now.

    public

    class TemplateSelector : DataTemplateSelector

     

    {

     

      public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)

     

      {

     

        if (object.ReferenceEquals(item, container))

     

     

          return null;

     

     

        return (!(item as MenuOption).IsSeparator) ? (Application.Current.RootVisual as Page2).Resources["itemTemplate"] as HierarchicalDataTemplate : (Application.Current.RootVisual as Page2).Resources["SeparatorTemplate"] as HierarchicalDataTemplate;

     

      }

    }



    <

    rad:HierarchicalDataTemplate x:Key="SeparatorTemplate" ItemsSource="{Binding Items}">

     

     

      <Rectangle Fill="Green" Height="2" Width="40" />

     

     

    </rad:HierarchicalDataTemplate>

     


  7. Answer
    Hristo
    Admin
    Hristo avatar
    832 posts

    Posted 23 Apr 2009 Link to this post

    Hi Rob,

    I think you can attach another ContainerBindingCollection with only one ContainerBinding and bind the MenuItem.Enabled property to IsSeparator property (thus preventing it from getting mouse and keyboard input).
    Or you can use StyleSelector and apply style to the MenuItem that will disable the item and will change the control templates so that it will look like separator (please note that RadMenuItem has four Templates and you should override them all). I've attached a modified Page including all the changes that need to be done in order to restyle RadMenuItem to look like Separator based on IsSeparator property.

    Let me know if you need additional information.

    Regards,
    Hristo
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Check out the tips for optimizing your support resource searches.
  8. MB
    MB avatar
    23 posts
    Member since:
    Aug 2007

    Posted 03 Nov 2009 Link to this post

    This is cool - but how do you handle an event on the container (RadMenuItem) this way?

    e.g. to handle the Click/Checked event?  (without going into the style)

    Thanks.
  9. Kaloyan
    Admin
    Kaloyan avatar
    920 posts

    Posted 06 Nov 2009 Link to this post

    Hi Mark Bailey,

    This is not an issue to worry about. The RadMenuItem internally creates a containers for its children(RadMenuItem). So you can use the  Click/Checked event without any problems. Let us know if you have other questions.

    Best wishes,
    Kaloyan
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  10. MB
    MB avatar
    23 posts
    Member since:
    Aug 2007

    Posted 06 Nov 2009 Link to this post

    Sorry, let me clarify.  Since the RadMenuItem is created internally, how do you declaratively attach an even to it?

     

    <ContainerBindings> works great to bind to properties, but I don't see how to attach event handlers in xaml.

     

    Thanks

  11. Valeri Hristov
    Admin
    Valeri Hristov avatar
    2252 posts

    Posted 06 Nov 2009 Link to this post

    Hi Mark,

    You could handle the events, declared by RadMenuItem (Checked, Click, etc.) on RadMenu:
    using Telerik.Windows;
    ...
    // the using clause is needed for the AddHandler extension method
    menu.AddHandler(RadMenuItem.CheckedEvent, OnMenuItemChecked);

    and using the OriginalSource of the event you could get a reference to the item that raised the event.

    However, I would strongly recommend binding IsChecked and the other properties that raise events to data items. It is much easier to handle the changes this way:
    http://demos.telerik.com/silverlight/#Menu/CheckableMenuItems

    And using ItemClick event on RadMenu instead of Click on each RadMenuItem:
    http://demos.telerik.com/silverlight/#Menu/FirstLook

    Instead of ItemClick/Click you could use the Command property that we introduced with Q3 (attached is a simple application that uses our commanding framework, but you could use commanding framework of your choice).

    Kind regards,
    Valeri Hristov
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
Back to Top
DevCraft banner