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

RadMenuItem.Items.Add

17 Answers 341 Views
Menu
This is a migrated thread and some comments may be shown as answers.
Glen
Top achievements
Rank 1
Glen asked on 27 Nov 2008, 10:34 PM
Hi,

I'm trying to dynamically alter the menu items in a RadMenu when another action occurs in my application.

I've tried menu.Items.Clear() and menu.Items.Add(). Both result in an InvalidOperationException being thrown with the detail "Operation not supported on read-only collection.".

Is there a way to alter the menu items at run time?

Thanks,

Glen

17 Answers, 1 is accepted

Sort by
0
Hristo
Telerik team
answered on 28 Nov 2008, 07:13 AM
Hi Glen,

ItemsControl.Items collection is ReadOnly if you set ItemsSource property. So in order to change to Items you should alter the ItemsSource collection. If your collection implements INotifyCollectionChange just remove the item from your collection and the change will be reflected automaticaly in RadMenu.

The other way is not to use ItemsSource. Just add items directly to Items property. This way the Items collection will not be readonly.

If you need more help, we'll be glad to help.


Best wishes,
Hristo
the Telerik team

Check out Telerik Trainer, the state of the art learning tool for Telerik products.
0
Glen
Top achievements
Rank 1
answered on 01 Dec 2008, 12:36 AM
Hi Hristo,

Thanks for that info, I can add items now.

My next stumbling block is that I don't know how to add sub items. My menu needs to be dynamic and will sometimes have 3 levels and sometimes have 4. So it will look something like:
Country
        -> State
            -> Province
                -> City

But not all states have provinces. If there are no provinces I don't want to have that level appearing in the menu.

So my code looks like:
foreach (var country in Countries)
{
    CountryMenu.Items.Add(country);
    foreach (var state in country.States)
    {
        // What goes here?
        CountryMenu.Items(Country).Items.Add(state); // This doesn't work. The item is the data object, not the RadMenuItem
    }
}

What I really need is a way to access the RadMenuitems, not the "Items" property so that I can add sub menu items.

I could create an xml doc or even just bind to the data structure, but I don't know how I'd exclude the menu layer if a state has provinces. Also, I need the leaf node in the menu to be clickable, and if I can't trap the OnClick method of the leaf node, I'm not sure how I'd know it's been clicked.

Do you have any thoughts how I could do this?

Thanks,

Glen
0
Hristo
Telerik team
answered on 01 Dec 2008, 09:23 AM
Hi Glen,

You can create an ObservableCollection from your data items and set them as ItemsSource on RadMenu. Then using HierarchicalDataTemplate you can create menu with unlimited nested leves.

Here is an example:
http://demos.telerik.com/silverlight/#Menu/DataSource

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.
0
Glen
Top achievements
Rank 1
answered on 01 Dec 2008, 11:13 PM
Hi Hristo,

I've seen that example and have implemented something similar. I was actually asking about something different.

What I am trying to do is have a menu structure where the number of sub menus is not fixed. I need it to be fully dynamic. As far as I can tell, using HierarchicalDataTemplate means that you're setting a template so that the first level menu is always of a certain type, then the second level menu is always of a certain (different) type. It won't allow me the flexibility of having different sub menu structures.

So what I want is:
Menu
    -> Australia
        ->Victoria
            ->Melbourne
            -> Bendigo
        ->NSW
            ->Sydney
    -> UK
        ->London
        ->Leeds

Do you see how under the Australia node there are two sub menu levels (state and city) where under the UK node there is only one level (city only).

Glen
0
Hristo
Telerik team
answered on 02 Dec 2008, 02:09 PM
Hi Glen,

Using HierarchicalDataTemplate allows you to create hirarchy. HierarchicalDataTemplate have ItemsSource property that tells the item from where to get its children.

I've attached a simple Page (UserControl) that demonstrate how to achieve dynamic MenuItems using classes like Country, State etc. You need to add it to existing project and add reference to our assemblies in order to run it.

There is a problem with menuitem which is not loaded but change its items. This problem will be fixed for the next release - service pack 2 (due to middle of december). If you need it earlier just open a support ticket and I will send you the hotfix.

If you need more help, I'll be glad to help


Greetings,
Hristo
the Telerik team

Check out Telerik Trainer, the state of the art learning tool for Telerik products.
0
Glen
Top achievements
Rank 1
answered on 04 Dec 2008, 12:26 AM
Hi Hristo,

Thankyou for the information, but you are still misunderstanding what I'm actually asking. I've seen that sample before and it works fine. But it doesn't do what I want it to do.

The example you have provided has dynamic menu data but I want dynamic menu structure.

I want to allow one of the sub menus to not even have a "Province" item. So it goes Country->State->City. The other sub menu should have the province. It should go Country->State->Province->City. Can you see that the structure of the menu is different? In this case, there is not a single class hierarchy that can be bound to the menu ItemSource to provide this.

Glen
0
Hristo
Telerik team
answered on 04 Dec 2008, 08:32 AM
Hello Glen,

Now I get what you want to achieve.

They way I see it you can use generic collection and fill it with items that have Name and Items properties. This way you can use a single HierarchicalDataTemplate. I've attached an updated version of the sample illustrating this approach.

The other way is to fill manually Items collection with RadMenuItem objects. This way you can take the RadMenuItem from Items collection with cast:

foreach (var country in Countries)  
{  
    RadMenuItem countryItem = new RadMenuItem() { Header = country.Name };  
    CountryMenu.Items.Add(countryItem);  
    foreach (var state in country.States)  
    {  
        RadMenuItem stateItem = new RadMenuItem() { Header = state.Name };  
        // Either use countryItem   
        countryItem.Items.Add(stateItem)  
        // Or if you don't have reference to countryItem you can take it like this;  
        //RadMenuItem countryItem = CountryMenu.Items[0] as RadMenuItem;  
    }  

I hope this help.
If you need more help, just drop me a line.


Kind regards,
Hristo
the Telerik team

Check out Telerik Trainer, the state of the art learning tool for Telerik products.
0
Glen
Top achievements
Rank 1
answered on 07 Dec 2008, 11:24 PM
Hi Hristo,

Thanks for the information. I tried adding RadMenuitems but I was getting exceptions thrown when the menu was displayed.

I like your suggestion of having a generic structure with Name and Item properties. I'll try that out.

Thanks,

Glen
0
Bichitra
Top achievements
Rank 1
answered on 17 Jan 2009, 04:54 AM
Hi,

I am getting the same problem here. I have created Menu. The main Menu contains  File, GoTo.

I have created MenuItems dynamically using menu,Items.Add() method. As per my requirment.  on the acton of any in my page the child Items are different. So I need the remove the all child Items and Add new Items under GoTo Main Menu Item.

When I am trying to  remove items under GoTo menu I am getting Parse error. on gotoItem.Items.Clear(); "AG_E_UNKNOWN_ERROR [Line: 1 Position: 1426]"
RadMenu --> rdmenu

 

RadMenuItem[] items = new RadMenuItem[rdmenu.Items.Count];

 

rdmenu.Items.ToArray().CopyTo(items, 0);

 

 

RadMenuItem gotoItem = (from menuItem in items

 

 

 

where string.Compare(menuItem.Tag.ToString(), "Goto", StringComparison.InvariantCultureIgnoreCase) == 0

 

 

 

select menuItem).Single();
gotoItem.Items.Clear();

Can u please help me to fix this issue.

this is the error :"   at MS.Internal.XcpImports.MethodEx(IntPtr ptr, String name, CValue[] cvData)\r\n   at MS.Internal.XcpImports.MethodEx(DependencyObject obj, String name)\r\n   at MS.Internal.XcpImports.Control_ApplyTemplate(Control control)\r\n   at System.Windows.Controls.Control.ApplyTemplate()\r\n   at Telerik.Windows.Controls.RadMenuItem.ChangeTemplate()\r\n   at Telerik.Windows.Controls.RadMenuItem.UpdateRole()\r\n   at Telerik.Windows.Controls.RadMenuItem.OnItemsChanged(NotifyCollectionChangedEventArgs e)\r\n   at System.Windows.Controls.ItemsControl.RaiseOnItemsChanged(NotifyCollectionChangedEventArgs e)\r\n   at System.Windows.Controls.ItemCollection.NotifyItemsControl(NotifyCollectionChangedEventArgs e)\r\n   at System.Windows.Controls.ItemCollection.RemoveAtImpl(Int32 index)\r\n   at System.Windows.PresentationFrameworkCollection`1.RemoveAt(Int32 index)\r\n   at System.Windows.Controls.ItemCollection.RemoveInternal(Object value)\r\n   at System.Windows.PresentationFrameworkCollection`1.Remove(T value)\r\n   at Xcel.Framework.RIA.ActivityManagement.CommonUI.Menu.notifyGotoMenuBuild_PropertyChanged(Object sender, PropertyChangedEventArgs e)"


 

 

0
Hristo
Telerik team
answered on 19 Jan 2009, 01:03 PM
Hi Bichitra,

Can you send us a simple project where we can investigate this issue. I have tried your case but there was no exception. Can you please check that you are using the latest version of our assemblies?
Also do you put UIElements in the Header property of RadMenuItem or just strings?

Waiting for your reply.

Best wishes,
Hristo
the Telerik team

Check out Telerik Trainer, the state of the art learning tool for Telerik products.
0
Bichitra
Top achievements
Rank 1
answered on 19 Jan 2009, 03:34 PM
Thanks for reply..

I have used old version ..  I  put UIElements in the Header property .

If there is no issues in new version so i will use that one.
Is there any issue to add UIElements in the Header property ?

Thanks
Bichitra



0
Hristo
Telerik team
answered on 19 Jan 2009, 04:24 PM
Hi Bichitra,

Unfortunately there is an issue when Header is populated with UIElement. RadMenuItem Template contains ContentPresenter (or in some themes ContentControl) that is bound to Header property. When template is changed Silverlight doesn't clean this binding and when the new template is applied is tries to bind to the same UI object in the Header. But this object have parent and cannot have other parent until the first binding is removed so an exception is raised.

We will try to find some workaround but for the moment I can think of one solution.
Theme changing is happening when you remove all the Items. So instead of removing all items try to leave one item then add some new items and at the end remove the item that that was left.

Like this:
private void Button_Click(object sender, RoutedEventArgs e)  
{  
    // Leave at least 1 item  
    for (int i = 1; i < menu1.Items.Count; i++)  
    {  
        menu1.Items.RemoveAt(1);  
    }  
 
    // Add the new items  
    menu1.Items.Add(new RadMenuItem() { Header = "asdasd" });  
 
    // remove the last item from the previos menu  
    menu1.Items.RemoveAt(0);  

Here menu1 is root RadMenuItem.
Let me know if this works for you.

Best wishes,
Hristo
the Telerik team

Check out Telerik Trainer, the state of the art learning tool for Telerik products.
0
Bichitra
Top achievements
Rank 1
answered on 20 Jan 2009, 05:49 AM
Hi,

Thanks  for helping.. It is working now.

Regards
Bichitra
0
Terry
Top achievements
Rank 1
answered on 16 Oct 2009, 08:34 PM
Hi:

I've got a similar problem, but I want to bind to a menu structure defined in a SQL Server database.  I can write the SQL to retrieve the structure and add the items one by one, but is there a way to bind the menu directly to a single query resultset or is it necessary to iterate over the items and levels?  If this is possible, can you point me at an example?
0
Kaloyan
Telerik team
answered on 22 Oct 2009, 08:02 AM
Hi Terry,

There is no problem to bind your SQL collection data directly to the ItemsSource property of the RadMenuItem. You can check our online data binding example of the RadMenu showing this approach. Let us know if you need any further assistance.

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
Eduardo Lorenzo
Top achievements
Rank 1
answered on 14 Apr 2010, 08:34 AM
Hi,

foreach (var country in Countries)  
{  
    RadMenuItem countryItem = new RadMenuItem() { Header = country.Name };  
    CountryMenu.Items.Add(countryItem);  
    foreach (var state in country.States)  
    {  
        RadMenuItem stateItem = new RadMenuItem() { Header = state.Name };  
        // Either use countryItem   
        countryItem.Items.Add(stateItem)  
        // Or if you don't have reference to countryItem you can take it like this;  
        //RadMenuItem countryItem = CountryMenu.Items[0] as RadMenuItem;  
    }  

This is well and good. Question tho, how do I add event handlers to the items?

Thanks in advance!


0
Kaloyan
Telerik team
answered on 19 Apr 2010, 09:20 AM
Hi Eduardo Lorenzo,

RadMenuItem control is exposing a whole lot of events(Click, MouseLeftButtonDown...etc.etc) that can be used for adding event handlers. Exactly which event are you looking for?

Kind regards,
Kaloyan
the Telerik team

Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
Tags
Menu
Asked by
Glen
Top achievements
Rank 1
Answers by
Hristo
Telerik team
Glen
Top achievements
Rank 1
Bichitra
Top achievements
Rank 1
Terry
Top achievements
Rank 1
Kaloyan
Telerik team
Eduardo Lorenzo
Top achievements
Rank 1
Share this question
or