This is a migrated thread and some comments may be shown as answers.

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

9 Answers 438 Views
Menu
This is a migrated thread and some comments may be shown as answers.
Rob
Top achievements
Rank 1
Rob asked on 15 Apr 2009, 07:24 PM
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.

9 Answers, 1 is accepted

Sort by
0
Boyan
Telerik team
answered on 21 Apr 2009, 11:55 AM
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.
0
Rob
Top achievements
Rank 1
answered on 21 Apr 2009, 07:14 PM
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
0
Hristo
Telerik team
answered on 22 Apr 2009, 11:38 AM
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.
0
Rob
Top achievements
Rank 1
answered on 22 Apr 2009, 01:51 PM
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>

 


0
Accepted
Hristo
Telerik team
answered on 23 Apr 2009, 06:49 AM
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.
0
MB
Top achievements
Rank 1
answered on 03 Nov 2009, 08:43 PM
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.
0
Kaloyan
Telerik team
answered on 06 Nov 2009, 09:29 AM
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.
0
MB
Top achievements
Rank 1
answered on 06 Nov 2009, 12:42 PM

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

0
Valeri Hristov
Telerik team
answered on 06 Nov 2009, 02:33 PM
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.
Tags
Menu
Asked by
Rob
Top achievements
Rank 1
Answers by
Boyan
Telerik team
Rob
Top achievements
Rank 1
Hristo
Telerik team
MB
Top achievements
Rank 1
Kaloyan
Telerik team
Valeri Hristov
Telerik team
Share this question
or