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

How can I have Header Context Menu and Row Context Menu together in RADGridView

28 Answers 1191 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Sanket Singhvi
Top achievements
Rank 1
Sanket Singhvi asked on 16 Aug 2010, 11:06 PM
I need separate context menu for Header and Rows. not able to find way to do it. Please provide an example.

Regards
Sanket

28 Answers, 1 is accepted

Sort by
0
Maya
Telerik team
answered on 17 Aug 2010, 07:21 AM
Hi Sanket Singhvi,

You can take a look at our demos where you will find examples both for adding context menus to the Rows and to the Headers. As the way they are appended is completely different and they are separate, there is no problem to create two distinct menus for single grid.
So, following up the logic shown in the examples, the Header Context Menu can be created by adding an additional class - GridViewHeaderMenu and enabled in xaml through telerikGridViewHeaderMenu:GridViewHeaderMenu.IsEnabled="True". On the other hand the Row Context Menu is added directly in xaml:

<telerik:RadContextMenu Opened="RadContextMenu_Opened" ItemClick="RadContextMenu_ItemClick">
     <telerik:RadContextMenu.Items>
            <telerik:RadMenuItem Header="Add" />
            <telerik:RadMenuItem Header="Edit" />
            <telerik:RadMenuItem Header="Delete" />
     </telerik:RadContextMenu.Items>
</telerik:RadContextMenu>

Furthermore, the Row Context Menu can be added to the grid on the RowLoaded event. 

Kind regards,
Maya
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
0
Sanket Singhvi
Top achievements
Rank 1
answered on 17 Aug 2010, 05:14 PM
Hi,

I tried but it didn't work. It just crashed. Could you please provide a small project having both the features.

Regards
Sanket
0
Maya
Telerik team
answered on 17 Aug 2010, 06:29 PM
Hello Sanket Singhvi,

The important thing here is that once you set the RowContextMenu, the HeaderContextMenu is overridden. 
So, what you need to do is to implement your custom logic inside a custom separate class - ContextMenus for example. Basically, it would be the same as the one shown in our demo for HeaderContextMenu. However, in your class - ContextMenus, you will have to check if the element clicked is GridViewCell or GridViewHeaderCell. Afterwards, depending on the clicked item, you will create the context menu with different RadMenuItems.
I am sending you a sample project illustrating the proposed solution.
 

Sincerely yours,
Maya
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
0
Ramyashree
Top achievements
Rank 1
answered on 21 Jan 2011, 08:37 AM
Hi,

I'm new to rad controls.... I'm not able to use RadContextMenu though it appears in the toolbox... If I try to add it in xaml, the following error is thrown.. Please let me know what needs to be done....

Error:
'The type 'telerik:RadContextMenu' was not found. Verify that you are not missing an assembly reference and that all referenced assemblies have been built. D:\Ramyashree\Country\Country\MainPage.xaml 92 26 Country'

Thanks and Regds.,
Ramya
0
MiroslavStantic
Top achievements
Rank 1
Iron
answered on 07 Oct 2011, 02:00 PM
Hi,

Could you please where and what you had to change in order to accomplish this? I have lots of code already in place and do not understand what I needed to change.

Thanks
Miroslav
0
Paul
Top achievements
Rank 1
answered on 29 Mar 2013, 02:04 PM
I reviewed the sample code but I'm afraid I find it deficient.  It seems that the GridVeiw is only capable of supporting a single context menu and the last one created wins.

In the example code provided you are using the GridViewHeaderMenu and dynamically constructing a conext menu based upon cell type.  With a product having several grids this solution does not lend itself well.  Certainly one could use inheritance to inherit from teh GridViewHeaderMenu but at the end of the day there will still be a seperate class for each context menu.

If the xaml is unremarked to allow the declarative ContextMenu then there is no context menu to the header.  How woud you duggest we keep the GridViewHeaderMenu agnostic of a standard GridRow context menu?

I cannot update to version 2013.1 220 until an issue I reported with the GridView is resolved. Until then I am using 2012.3.1017 with an expectation to upgrade to 2013.4.x when it is released.  This is still relevant to 2012.3.1017.

Thanks
Paul
0
Maya
Telerik team
answered on 03 Apr 2013, 11:15 AM
Hi Paul,

Generally, if you have different grids, all you need to do is to attach the behavior for creating a context menus. Do you have any troubles with the implementation or incorrect functionality ?

Kind regards,
Maya
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Paul
Top achievements
Rank 1
answered on 04 Apr 2013, 04:59 PM
The main issue I have is within a single gird.  I would like to continue to use the GridViewHeaderMenu that you have in your examples but I need an entirely different menu for the rows.  Yes, I could create a behavior for the grid as suggested in this thread which will construct a menu in a class.  However, the row context menu has composite controls as MenuItems.  These controls have DependancyProperties which I am databinding to in my xaml. 

Thanks

Paul
0
Maya
Telerik team
answered on 05 Apr 2013, 08:40 AM
Hello Paul,

In this case, what you can try is to create your context menu as a resource for example or as a new control and open it once you clicked on a row. Still, you could try handling MouseRightButton event instead, verify what is the element you clicked on and open the menu you want.
It could be something like follows:

public class GridViewHeaderMenu
    {
        // The logic here is the same as the one from the sample project attached above.
 
        private void Attach()
        {
            if (this.grid != null)
            {
                this.grid.MouseRightButtonDown += new System.Windows.Input.MouseButtonEventHandler(OnMouseRightButtonDown);
            }
        }
 
        void OnMouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            var clickedElement = e.OriginalSource as FrameworkElement;
            if (clickedElement.ParentOfType<GridViewHeaderCell>() != null)
            {
                var menu = new RadContextMenu();
                menu.Items.Add(new RadMenuItem() { Header = "HeaderMenu" });
                menu.IsOpen = true;
            }
            else if (clickedElement.ParentOfType<GridViewCell>() != null)
            {
                var menu = Application.Current.Resources["RowContextMenu"] as RadContextMenu;
                menu.IsOpen = true;
            }
        }
    }

In this case the menu is declared in the Resources section of the App. However, you can do that wherever appropriate for your scenario and get it here.
Will that approach meet your requirements ?  

Regards,
Maya
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Paul
Top achievements
Rank 1
answered on 17 Apr 2013, 02:50 PM
Can you show how you would do this with the GridViewHeaderMenu.cs that you have in other examples?  I would like to maintain one copy of this class and becasue it is designed to be referenced in the XAML, with the DependancyProperty for IsEnabled, it is not going in very well.

For the row conetxt menu I will try your suggestion of the resource.

Thank you
0
Maya
Telerik team
answered on 19 Apr 2013, 11:06 AM
Hi Paul,

Could you clafity a bit ? Do you want to have context menu defined in the resources and use it for the header ?  

Greetings,
Maya
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Paul
Top achievements
Rank 1
answered on 19 Apr 2013, 01:18 PM
Sure, I already use a class based upon your example of a header context menu.  This is using a DependancyProperty and is designed to be referenced declaratively.  Using your suggestion I would call it from the C# code but because how it is designed it does not function in this manor.  I don't want to discard it and replace it with a design not intended to be used in the declarative code because it is used elsewhere.  I also don't want to create a new version of that specifically for the C# code because then I two sets of code doing the same thing to keep synchronized.

Does this help?

Thank you

Paul
0
Nick
Telerik team
answered on 24 Apr 2013, 01:40 PM
Hello Paul,

The same approach that Maya suggested can be used for the HeaderCell as well. The only thing you have to do is define the HeaderContextMenu structure in your resources, after that it is all analogical. 

Do you have any problems achieving that? 


Kind regards,
Nikolay Vasilev
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Paul
Top achievements
Rank 1
answered on 02 May 2013, 05:54 PM
Thank you. 

We are very close but I am facing one problem from this.  Related to ticket 676477, the Grid takes focus when teh context menu is closed.  I was getting around this with the declarative mechanism because I had a reference in the code behind to a UserControl that the context menu is opening.  On the Dispatcher I was setting focus to the subsequent control so a control hosted in a PopUp invoked by my UserControl could have focus.  I have the following inplace in the context menu which is getting called:
RoutedEventArgs routedEventArgs = new RoutedEventArgs(MyContextMenu.ContextMenuClosed);
RaiseEvent(routedEventArgs);

and in the XAML:
<telerik:RadGridView my:MyContextMenu.IsEnabled="True" my:MyContextMenu.ContextMenuClosed="GridContextMenu_Closed"

Since the XAML does not have an issue with the ContextMenuClosed event I know the event is proeprly registered.  It looks as if the context menu is created twice, as I put a break point on the constructor.   How can the event be raised on the same instance that is being set IsEnabled="True"?

Thank you
Paul
0
Maya
Telerik team
answered on 07 May 2013, 04:34 PM
Hi Paul,

I believe I am missing something here. Could you clarify what the problem is ? Do you want an event to be raised for an context menu instance that is not enabled ? How are both menus related ?
Will it be possible to update the project attached above or the one from the other ticket (676477) and send it back so that I can see your exact settings and the issue you are struggling with ? 

All the best,
Maya
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Paul
Top achievements
Rank 1
answered on 13 May 2013, 07:16 PM
I created 692704 to unclude the sample application.

Thanks

Paul
0
Maya
Telerik team
answered on 14 May 2013, 03:14 PM
Hi Paul,

Thanks for the project. My recommendation would be to run through this article on how to create an attached event and if possible, try to keep the logic inside the menu class rahter than exposing it in the code-behind.
Let me know in case you have any further troubles. 

Regards,
Maya
the Telerik team

Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

0
Nargis
Top achievements
Rank 1
answered on 21 Oct 2014, 08:13 AM
Hi Maya,

I have the same issue and need the context menu for the grid header, grid row and grid child row. I modified your sample project so far, that I take the dependency property ContextMenuProperty instead of creating new context by clicking. My problem is that the content of the context menu appears either on parent grid row or on child grid row, depending on where I clicked first. However, the content should be displayed for both the parent grid row and the child grid row for.

Here is my code:
MainWindow.xaml
<Window.Resources>
        <my:MyViewModel x:Key="MyViewModel"/>
    </Window.Resources>
    <Grid DataContext="{StaticResource MyViewModel}">
        <telerik:RadGridView Name="playersGrid"  ColumnWidth="*"
                                     my:GridViewHeaderMenu.IsEnabled="True"
                                     my:GridViewHeaderMenu.RowContextMenu="{Binding PositionContextMenu}"
                                     ItemsSource="{Binding Clubs}"
                                     SelectedItem="{Binding SelectedItem}"
                                     AutoGenerateColumns="False">
            <telerik:RadGridView.Columns>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding Name}"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding Established}"
                                            Header="Est."
                                            DataFormatString="{}{0:yyyy}"/>
                <telerik:GridViewDataColumn DataMemberBinding="{Binding StadiumCapacity}"
                                            Header="Stadium"
                                            DataFormatString="{}{0:N0}"/>
            </telerik:RadGridView.Columns>
            <telerik:RadGridView.ChildTableDefinitions>
                <telerik:GridViewTableDefinition/>
            </telerik:RadGridView.ChildTableDefinitions>
            <telerik:RadGridView.HierarchyChildTemplate>
                <DataTemplate>
                    <telerik:RadGridView Name="playersGrid"
                                     ItemsSource="{Binding Players}"
                                     AutoGenerateColumns="False"
                                     my:GridViewHeaderMenu.IsEnabled="True"
                                     my:GridViewHeaderMenu.RowContextMenu="{Binding Path=DataContext.PositionContextMenu,
                                                                            RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type my:MainWindow}}}">
                        <telerik:RadGridView.Columns>
                            <telerik:GridViewDataColumn DataMemberBinding="{Binding Name}"/>
                            <telerik:GridViewDataColumn DataMemberBinding="{Binding Number}"/>
                            <telerik:GridViewDataColumn DataMemberBinding="{Binding Position}"/>
                            <telerik:GridViewDataColumn DataMemberBinding="{Binding Country}"/>
                        </telerik:RadGridView.Columns>
                    </telerik:RadGridView>
                </DataTemplate>
            </telerik:RadGridView.HierarchyChildTemplate>
        </telerik:RadGridView>
    </Grid>
MyViewModel.cs
public class MyViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
 
        private ObservableCollection<Club> clubs;
        private ObservableCollection<Player> players;
        private object selectedItem;
 
 
        private Telerik.Windows.Controls.RadContextMenu _positionsContextMenu;
        public Telerik.Windows.Controls.RadContextMenu PositionContextMenu
        {
            get {return _positionsContextMenu;}
            set
            {
                _positionsContextMenu = value;
                this.OnPropertyChanged("PositionContextMenu");
            }
        }
 
        public MyViewModel()
        {
            InitPositionsContextMenu();
        }
 
        private void InitPositionsContextMenu()
        {
            PositionContextMenu = new Telerik.Windows.Controls.RadContextMenu();
            PositionContextMenu.Items.Add(new RadMenuItem() { Header ="Add"});
            PositionContextMenu.Items.Add(new RadMenuItem() { Header ="Edit"});
            PositionContextMenu.Items.Add(new RadMenuItem() { Header ="Delete"});
        }
...
}

GridViewHeaderMenu.cs

....
public static readonly DependencyProperty RowContexMenuProperty
          = DependencyProperty.RegisterAttached("RowContextMenu", typeof(RadContextMenu), typeof(GridViewHeaderMenu),
              new PropertyMetadata(new PropertyChangedCallback(OnRowContextMenuPropertyChanged)));
 
        public static void SetRowContextMenu(DependencyObject dependencyObject, RadContextMenu value)
        {
            dependencyObject.SetValue(RowContexMenuProperty, value);
        }
 
        public static RadContextMenu GetRowContextMenu(DependencyObject dependencyObject)
        {
            return dependencyObject.GetValue(RowContexMenuProperty) as RadContextMenu;
        }
 
        private static void OnRowContextMenuPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            SetRowContextMenu(dependencyObject, (RadContextMenu)e.NewValue);
        }
 
void OnMenuOpened(object sender, RoutedEventArgs e)
        {
            RadContextMenu menu = (RadContextMenu)sender;
            GridViewHeaderCell cell = menu.GetClickedElement<GridViewHeaderCell>();
            GridViewCell gridCell = menu.GetClickedElement<GridViewCell>();
             
            if (cell != null)
            {
                menu.Items.Clear();
 
                RadMenuItem item = new RadMenuItem();
                item.Header = "Header Context Menu";
                menu.Items.Add(item);
 
            }
            else if(gridCell != null)
            {              
                menu.Items.Clear();
                 
                RadMenuItem item = new RadMenuItem();
                RadContextMenu rowMenu = gridCell.ParentRow.ParentOfType<RadGridView>().GetValue(RowContexMenuProperty) as RadContextMenu;
                 
                //item.Header = "Row Context Menu";
                //menu.Items.Add(rowMenu);
                AddMenuItems(menu, rowMenu);
                 
            }
            else
            {
                menu.IsOpen = false;
            }
        }
 
 private readonly List<RadMenuItem> _rowItems = new List<RadMenuItem>();
        private void AddMenuItems(RadContextMenu menu, RadContextMenu clickedElementMenu)
        {
            if (clickedElementMenu != null)
            {
                menu.Items.Clear();
                if (clickedElementMenu.Items.Count > 0)
                {
                    List<RadMenuItem> menuitems = new List<RadMenuItem>();
                    foreach (var item in clickedElementMenu.Items)
                    {
                        menuitems.Add(item as RadMenuItem);
                    }
                    foreach (RadMenuItem item in menuitems)
                    {
                        clickedElementMenu.Items.Remove(item);
                        if (_rowItems.Contains(item) == false)
                        {
                            _rowItems.Add(item);
                        }
                    }
                }
                if (_rowItems.Count > 0)
                {
                    foreach (var item in _rowItems)
                    {
                        menu.Items.Add(item);
                    }
                }
            }
            else
            {
                menu.IsOpen = false;
            }
        }
...

Could you tell me what am I missing?
Thank you a lot in advance!
Best regards
Nargis
0
Maya
Telerik team
answered on 23 Oct 2014, 08:40 AM
Hello Nargis,

I tested the code you provided and actually, the menu does not open in the child grid on my side. Please make sure that the menu is not null. Why don't you create the menu inside the GridViewHeaderMenu class and use it there rather than placing visual element in your ViewModel ?



Regards,
Maya
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
Nargis
Top achievements
Rank 1
answered on 23 Oct 2014, 09:07 AM
Hello Maya,

that is my problem. If I click with mouse left button on parent grid row first the menu appears always only in the parent grid row and never on child grind row. After restarting the application if I click with mouse left button on child grid row first the menu appears always only in the child grid row and never on parent grind row.
I must take dependency Property because I use GridViewHeaderMenu-class for different ViewModels with different context menu.

Do you have any idea why the context menu for the second-clicked grid is always empty.
Thank you a lot!
Best regards
Nargis
0
Nargis
Top achievements
Rank 1
answered on 27 Oct 2014, 08:18 AM
Hello again,

The behavior, that I have explained in the preview post, I get If I add the following code snippet in the method OnMenuOpened(), in the line numbers 15-18. I missed to add this code in the post preview. I apologize for that.

01.void OnMenuOpened(object sender, RoutedEventArgs e)
02.        {
03.            ...
04.            if (cell != null)
05.            {
06.                ...
07. 
08.            }
09.            else if(gridCell != null)
10.            {              
11.                menu.Items.Clear();
12.                 
13.                RadMenuItem item = new RadMenuItem();
14.                RadContextMenu rowMenu = gridCell.ParentRow.ParentOfType<RadGridView>().GetValue(RowContextMenuProperty) as RadContextMenu;
15.                if (rowMenu == null)
16.                {
17.                    rowMenu = ((Telerik.Windows.Controls.GridView.GridViewDataControl)(gridCell.ParentRow.ParentOfType<RadGridView>())).ParentRow.ParentOfType<RadGridView>().GetValue(RowContextMenuProperty) as RadContextMenu;
18.                }
19.                //item.Header = "Row Context Menu";
20.                //menu.Items.Add(rowMenu);
21.                AddMenuItems(menu, rowMenu);
22.                 
23.            }
24.            else
25.            {
26.                menu.IsOpen = false;
27.            }
28.        }

I hope you have any tip for my problem.
Thank you a lot!
Best regards
Nargis
0
Maya
Telerik team
answered on 28 Oct 2014, 08:07 AM
Hello Nargis,

The context menu is initialized only once in the ViewModel and not for every RadGridView instance. Then what happens is that you trigger OnMenuOpen, the code pass through - rowMenu == null, initializes it and then in AddMenuItems method you clear the items from the initial instance of RowContextMenu:
foreach (RadMenuItem item in menuitems)
                   {
                       clickedElementMenu.Items.Remove(item);
                       if (_rowItems.Contains(item) == false)
                       {
                           _rowItems.Add(item);
                       }
                   }


Then when the menu for the inner grid should be created, the code passes through menu == null, initializes new instance, but then " if (clickedElementMenu.Items.Count > 0) " returns false since you already cleared the items when you created the context menu for the previous grid. 
So, you need to modify the logic so that it corresponds to your requirements, but without clearing the information of the items. 


Regards,
Maya
Telerik
 

Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

 
0
Luis Henrique
Top achievements
Rank 1
answered on 25 Aug 2020, 07:03 PM
Hi, the problem with this code is that the context menu is not opened where it was clicked. It just opens on the top left of the main window.
0
Dinko | Tech Support Engineer
Telerik team
answered on 28 Aug 2020, 08:19 AM

Hello Luis,

It seems that the PlacementTarget property of the RadContextMenu is not set on your side. Can you double-check if the PlacementTarget property of the control is set on the element which you want to show it?

Regards,
Dinko
Progress Telerik

Five days of Blazor, Angular, React, and Xamarin experts live-coding on twitch.tv/CodeItLive , special prizes and more, for FREE?! Register now for DevReach 2.0(20).

0
Luis Henrique
Top achievements
Rank 1
answered on 28 Aug 2020, 07:03 PM

Hello, thanks for the response.

Indeed, it isn't set.

How would I set it to open exactly where the user right clicked to open the grid context menu in the first place?

0
Dinko | Tech Support Engineer
Telerik team
answered on 02 Sep 2020, 08:59 AM

Hi Luis,

Thank you for the confirmation.

By default, the RadContextMenu should open on a mouse position. For example, using the following code snippet:

<TextBox Width="200" Height="50" Text="Some Text">
    <telerik:RadContextMenu.ContextMenu>
        <telerik:RadContextMenu>
            <telerik:RadMenuItem Header="Item 1"/>
            <telerik:RadMenuItem Header="Item 2"/>
            <telerik:RadMenuItem Header="Item 3"/>
        </telerik:RadContextMenu>
    </telerik:RadContextMenu.ContextMenu>
</TextBox>

May I ask you to share more information regarding your scenario. If you can create a sample project which mimics your implementation, that will be great.

Regards,
Dinko
Progress Telerik

Five days of Blazor, Angular, React, and Xamarin experts live-coding on twitch.tv/CodeItLive , special prizes and more, for FREE?! Register now for DevReach 2.0(20).

0
Luis Henrique
Top achievements
Rank 1
answered on 02 Sep 2020, 09:10 PM

Hello Dinko,

I'm trying to do exactly what the topic says: open a header and row context menu, with the ability to grab some of the menu from the Resources (previously set up in XAML).

I followed/copied the exact code that Maya provided above.

https://www.telerik.com/forums/how-can-i-have-header-context-menu-and-row-context-menu-together-in-radgridview#LhJ2EB3iX0CGLgDg6A8-Iw

 

And with that the ContextMenu does not open on the right position. As there is no PlacementTarget indeed, but I do not know how to make it work in that context/code provided.

 

Thanks

0
Dinko | Tech Support Engineer
Telerik team
answered on 07 Sep 2020, 12:02 PM

Hi Luis,

May I ask you to check our 2 SDK examples, which demonstrate how you can add RadContextMenu to the RadGridView control.

Give these two SDK examples a try and let me know if further questions arise.

Regards,
Dinko
Progress Telerik

Five days of Blazor, Angular, React, and Xamarin experts live-coding on twitch.tv/CodeItLive , special prizes and more, for FREE?! Register now for DevReach 2.0(20).

Tags
GridView
Asked by
Sanket Singhvi
Top achievements
Rank 1
Answers by
Maya
Telerik team
Sanket Singhvi
Top achievements
Rank 1
Ramyashree
Top achievements
Rank 1
MiroslavStantic
Top achievements
Rank 1
Iron
Paul
Top achievements
Rank 1
Nick
Telerik team
Nargis
Top achievements
Rank 1
Luis Henrique
Top achievements
Rank 1
Dinko | Tech Support Engineer
Telerik team
Share this question
or