Context Menus
- 7 minutes to read
The GridControl can display pop-up menus that allow users to manage data (apply grouping and sorting, display summaries, and so on) and customize the View (show or hide its UI elements). These context menus can be customized.
Context Menus Overview
To obtain the context menu displayed within a View, use the GridViewBase.GridMenu property.
Customize Context Menus
In XAML
Use the View’s properties:
Menu Type | Property |
---|---|
TableView TableView.CompactModeFilterElementMenuCustomizations | |
TreeListView TreeListView.CompactModeFilterElementMenuCustomizations TreeListView.CompactModeFilterMergeElementMenuCustomizations |
These properties return a BarManagerActionCollection object (bar items, links, and actions).
In Code
Handle the DataViewBase.ShowGridMenu event.
Examples
Bind to a Column, Row, and TableView in RowCellMenuCustomizations
To bind a cell’s context menu to a column, row or TableView, use the default binding source or the attached GridPopupMenu.GridMenuInfo property.
<dxg:TableView Tag="Test value">
<dxg:TableView.RowCellMenuCustomizations>
<dxb:BarButtonItem Content="{Binding Path=Column.FieldName}" />
<dxb:BarButtonItem Content="{Binding Path=Row.Row.Name}" />
<dxb:BarButtonItem Content="{Binding Path=View.Tag}" />
</dxg:TableView.RowCellMenuCustomizations>
</dxg:TableView>
<!-- OR -->
<dxg:TableView Tag="Test value">
<dxg:TableView.RowCellMenuCustomizations>
<dxb:BarButtonItem Content="{Binding Path=(dxg:GridPopupMenu.GridMenuInfo).Column.FieldName, RelativeSource={RelativeSource Self}}" />
<dxb:BarButtonItem Content="{Binding Path=(dxg:GridPopupMenu.GridMenuInfo).Row.Row.Name, RelativeSource={RelativeSource Self}}" />
<dxb:BarButtonItem Content="{Binding Path=(dxg:GridPopupMenu.GridMenuInfo).View.Tag, RelativeSource={RelativeSource Self}}" />
</dxg:TableView.RowCellMenuCustomizations>
</dxg:TableView>
Rename Standard Menu Items
The following example renames the “Customize…” item in the summary panel:
In XAML
Use the bar‘s UpdateAction and specify the item name.
<dxg:TableView.TotalSummaryMenuCustomizations>
<dxb:UpdateAction ElementName="{x:Static dxg:DefaultSummaryMenuItemNames.Customize}" PropertyName="Content" Value="Edit..." />
</dxg:TableView.TotalSummaryMenuCustomizations>
In Code
Subscribe to the DataViewBase.ShowGridMenu event and change the item name.
<dxg:TableView ShowGridMenu="ShowGridMenu" />
using DevExpress.Xpf.Grid;
//...
void ShowGridMenu(object sender, GridMenuEventArgs e) {
if (e.MenuType != GridMenuType.TotalSummary)
return;
BarItem item = e.Items.FirstOrDefault(x => x.Name == DefaultSummaryMenuItemNames.Customize);
if (item != null)
item.Content = "Edit...";
}
Add Cell and Column Menu Items to a Column
In XAML
Use the RowCellMenuCustomizations/ColumnMenuCustomizations properties and binding paths from the Bind to a Column, Row, and TableView in RowCellMenuCustomizations example.
<Window.Resources>
<dxmvvm:ObjectToObjectConverter x:Key="fieldNameToVisibleConverter" DefaultTarget="False">
<dxmvvm:MapItem Source="Visits" Target="True" />
</dxmvvm:ObjectToObjectConverter>
</Window.Resources>
...
<dxg:TableView>
<dxg:TableView.RowCellMenuCustomizations>
<dxb:BarButtonItem Content="Item 1" IsVisible="{Binding Column.FieldName, Converter={StaticResource fieldNameToVisibleConverter}}" />
</dxg:TableView.RowCellMenuCustomizations>
<dxg:TableView.ColumnMenuCustomizations>
<dxb:BarButtonItem Content="Item 2" IsVisible="{Binding Column.FieldName, Converter={StaticResource fieldNameToVisibleConverter}}" />
</dxg:TableView.ColumnMenuCustomizations>
</dxg:TableView>
In Code
Subscribe to the DataViewBase.ShowGridMenu event and specify e.MenuInfo.Column.FieldName in the event handler.
<dxg:TableView ShowGridMenu="TableView_ShowGridMenu" />
void TableView_ShowGridMenu(object sender, GridMenuEventArgs e) {
if (e.MenuInfo.Column.FieldName != "Visits")
return;
switch (e.MenuType) {
case GridMenuType.RowCell:
e.Customizations.Add(new BarButtonItem { Content = "Item 1" });
break;
case GridMenuType.Column:
e.Customizations.Add(new BarButtonItem { Content = "Item 2" });
break;
}
}
Show Different Cell Menu Items Depending on a Property Value
The following example demonstrates how to show the row cell’s context menu item if you sort data against the current column:
In XAML
Use RowCellMenuCustomizations and binding paths from the Bind to a Column, Row, and TableView in RowCellMenuCustomizations example.
<dxg:TableView>
<dxg:TableView.RowCellMenuCustomizations>
<dxb:BarButtonItem Content="Item 1" IsVisible="{Binding Column.IsSorted}" />
<dxb:BarButtonItem Content="Item 2" />
</dxg:TableView.RowCellMenuCustomizations>
</dxg:TableView>
In Code
Subscribe to the DataViewBase.ShowGridMenu event and get column objects from e.MenuInfo.
<dxg:TableView ShowGridMenu="TableView_ShowGridMenu" />
void TableView_ShowGridMenu(object sender, GridMenuEventArgs e)
{
if (e.MenuType != GridMenuType.RowCell)
return;
GridCellMenuInfo info = (GridCellMenuInfo)e.MenuInfo;
ColumnBase item = (ColumnBase)info.Column;
if (item.IsSorted)
e.Customizations.Add(new BarButtonItem { Content = "Item 1" });
e.Customizations.Add(new BarButtonItem { Content = "Item 2" });
}
Show Different Cell Menu Items Depending on a Node Level
The following example demonstrates how to show a row cell’s context menu for a node level:
In XAML
Use the RowCellMenuCustomizations property and bind the BarItem.IsVisible property to the current node’s level.
<Window.Resources>
<dxmvvm:ObjectToObjectConverter x:Key="levelToVisibleConverter" DefaultTarget="False">
<dxmvvm:MapItem Source="1" Target="True" />
</dxmvvm:ObjectToObjectConverter>
</Window.Resources>
...
<dxg:TreeListView>
<dxg:TreeListView.RowCellMenuCustomizations>
<dxb:BarButtonItem Content="Item 1" IsVisible="{Binding Row.Level, Converter={StaticResource levelToVisibleConverter}}" />
</dxg:TreeListView.RowCellMenuCustomizations>
</dxg:TreeListView>
In Code
Subscribe to the DataViewBase.ShowGridMenu event and get the current node from the e.MenuInfo object.
<dxg:TreeListView ShowGridMenu="TreeListView_ShowGridMenu" />
void TreeListView_ShowGridMenu(object sender, GridMenuEventArgs e) {
if (e.MenuType != GridMenuType.RowCell)
return;
GridCellMenuInfo info = (GridCellMenuInfo)e.MenuInfo;
TreeListRowData rowData = (TreeListRowData)info.Row;
if (rowData.Level == 1)
e.Customizations.Add(new BarButtonItem { Content = "Item 1" });
}
Remove Menu Items
The following example removes an item from the Total Summary panel‘s context menu:
Note
A complete sample project is available at https://github.com/DevExpress-Examples/how-to-customize-a-grids-context-menu-e1925.
In XAML
Add the RemoveBarItemAndLinkAction object to the DataViewBase.TotalSummaryMenuCustomizations collection. Specify the BarItemActionBase.ItemName property with the menu item name from the DefaultSummaryMenuItemNames class.
<dxg:TableView.TotalSummaryMenuCustomizations>
<dxb:RemoveBarItemAndLinkAction ItemName="{x:Static dxg:DefaultSummaryMenuItemNames.Customize}" />
</dxg:TableView.TotalSummaryMenuCustomizations>
In Code
Handle the DataViewBase.ShowGridMenu event.
<dxg:TableView ShowGridMenu="ShowGridMenu" />
void ShowGridMenu(object sender, GridMenuEventArgs e) {
if (e.MenuType == GridMenuType.TotalSummary) {
e.Customizations.Add(new RemoveAction { ElementName = DefaultSummaryMenuItemNames.Customize });
}
}
Add Menu Items to a Specific Position
The following example demonstrates how to add a custom menu item to a grid column’s context menu:
Note
A complete sample project is available at https://github.com/DevExpress-Examples/how-to-customize-a-grids-context-menu-e1925.
In XAML
Add a bar item (for example, BarCheckItem) to the DataViewBase.ColumnMenuCustomizations collection and specify item properties. Attach the BarItemLinkActionBase.ItemLinkIndex property to this item to insert it into a specific position.
<dxg:TableView.ColumnMenuCustomizations>
<dxb:BarCheckItem Name="checkItem1" Content="Checked" IsChecked="True" dxb:BarItemLinkActionBase.ItemLinkIndex="0" />
<dxb:BarItemLinkSeparator dxb:BarItemLinkActionBase.ItemLinkIndex="1" />
</dxg:TableView.ColumnMenuCustomizations>
private void customItem1_CheckedChanged(object sender, ItemClickEventArgs e) {
// do something...
}
In Code
Handle the ShowGridMenu event.
<dxg:TableView ShowGridMenu="ShowGridMenu" />
void ShowGridMenu(object sender, GridMenuEventArgs e) {
if (e.MenuType == GridMenuType.Column) {
BarCheckItem item1 = new BarCheckItem { Content = "Checked", IsChecked = true };
BarItemLinkActionBase.SetItemLinkIndex(item1, 0);
e.Customizations.Add(item1);
BarItemLinkSeparator item2 = new BarItemLinkSeparator();
BarItemLinkActionBase.SetItemLinkIndex(item2, 1);
e.Customizations.Add(item2);
}
}
Add Custom Row Cell’s Context Menu
The following example shows how to create a context menu that allows users to copy a cell’s data and remove rows:
Note
A complete sample project is available at https://github.com/DevExpress-Examples/how-to-access-and-remove-rows-by-using-a-custom-cells-context-menu-e1558.
<dxg:TableView x:Name="view" AutoWidth="True">
<dxg:TableView.RowCellMenuCustomizations>
<dxb:BarButtonItem Name="deleteRowItem" Content="Delete" ItemClick="deleteRowItem_ItemClick" />
<dxb:BarButtonItem Name="copyCellDataItem" Content="Copy Cell Data" ItemClick="copyCellDataItem_ItemClick" />
</dxg:TableView.RowCellMenuCustomizations>
</dxg:TableView>
private void copyCellDataItem_ItemClick(object sender, ItemClickEventArgs e) {
GridCellMenuInfo menuInfo = view.GridMenu.MenuInfo as GridCellMenuInfo;
if (menuInfo != null && menuInfo.Row != null) {
string text = "" +
grid.GetCellValue(menuInfo.Row.RowHandle.Value, menuInfo.Column as GridColumn).ToString();
Clipboard.SetText(text);
}
}
private void deleteRowItem_ItemClick(object sender, ItemClickEventArgs e) {
GridCellMenuInfo menuInfo = view.GridMenu.MenuInfo as GridCellMenuInfo;
if (menuInfo != null && menuInfo.Row != null)
view.DeleteRow(menuInfo.Row.RowHandle.Value);
}