Regards
Sanket
28 Answers, 1 is accepted
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
I tried but it didn't work. It just crashed. Could you please provide a small project having both the features.
Regards
Sanket
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.
Maya
the Telerik team
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
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
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
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 ?
Maya
the Telerik team
Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.
Thanks
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.
For the row conetxt menu I will try your suggestion of the resource.
Thank you
Could you clafity a bit ? Do you want to have context menu defined in the resources and use it for the header ?
Maya
the Telerik team
Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.
Does this help?
Thank you
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?
Nikolay Vasilev
the Telerik team
Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.
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
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 ?
Maya
the Telerik team
Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.
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.
Maya
the Telerik team
Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.
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
>
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
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.
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
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
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.
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).
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?
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).
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
Hi Luis,
May I ask you to check our 2 SDK examples, which demonstrate how you can add RadContextMenu to the RadGridView control.
- RadContextMenuForRadGridView: This example demonstrates how to use RadContextMenu with RadGridView and how to set different items based on the part of RadGridView that has been clicked.
- RadContextMenuAndRadGridViewMVVM: This example demonstrates how to use RadContextMenu for RadGridView in MVVM pattern.
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).