Popup and Context Menus
- 13 minutes to read
This topic shows how to customize a Data Grid’s built-in popup menus, override the default menu item actions, and use events to create custom popup menus.
Note
This topic does not cover in-place editors’ menu items.
Built-In Context Menus
The Data Grid’s Grid Views and Banded Grid Views have five built-in context menus.
Column Header Menu (right-click a column header)
Menu Item Visibility controlled by Menu Availability GridOptionsMenu.EnableColumnMenu Show/Hide Auto Filter Row command GridOptionsMenu.ShowAutoFilterRowItem Group Interval sub-menu (available for date-time columns) GridOptionsMenu.ShowDateTimeGroupIntervalItems Sort by Summary sub-menu (available for grouping columns) GridOptionsMenu.ShowGroupSortSummaryItems Conditional Formatting sub-menu (hidden by default) GridOptionsMenu.ShowConditionalFormattingItem Show/Hide Footer command (hidden by default) GridOptionsMenu.ShowFooterItem Group Summary Editor action (hidden by default; available for grouping columns) GridOptionsMenu.ShowGroupSummaryEditorItem Split/Remove Split command (available when Data Grid is hosted inside a GridSplitContainer) GridOptionsMenu.ShowSplitItem Example:
Group Panel Menu (right-click the Group Panel)
Menu Item Visibility controlled by Menu Availability GridOptionsMenu.EnableGroupPanelMenu ‘Split’/‘Remove Split’ command (available when Data Grid is hosted inside a GridSplitContainer) GridOptionsMenu.ShowSplitItem Summary Menu (right-click the total summary footer and group summary footers)
Menu Item Visibility controlled by Menu Availability GridOptionsMenu.EnableFooterMenu ‘Add New Summary’ sub-menu (hidden by default; not supported for group summary footers) GridOptionsMenu.ShowAddNewSummaryItem Auto-Filter Row Menu (click a condition selector in the Auto-Filter Row)
Menu Item Visibility controlled by Menu Availability GridOptionsFilter.AllowAutoFilterConditionChange Row Menu (right-click a data row or group row)
This menu is initially empty and thus is not displayed. Handle the GridView.PopupMenuShowing event to add custom commands to the row menu. See the Add Custom Items to Built-In Menus section for an example.
The properties the Views provide can affect the availability of certain items in these menus. For instance, when you disable the GridOptionsCustomization.AllowSort option, the “Sort Ascending” and “Sort Descending” items are automatically deactivated in the Column Header Menu.
Not all menu items can be hidden using the View’s properties. To control the visibility of any menu item, use the GridView.PopupMenuShowing event as described below.
Customize, Hide and Disable Default Menu Items
To customize menu items (for example, change their captions and visibility), handle the GridView.PopupMenuShowing event. This event fires each time the menu is invoked.
The event’s e.Menu parameter allows you to get the displayed menu. You can iterate through the e.Menu.Items collection or call the e.Menu.Find and e.Menu.FindAll methods to access individual menu items. To hide or remove certain menu items, use the e.Menu.Hide and e.Menu.Remove methods. These methods accept menu item identifiers as parameters. Refer to PopupMenuShowingEventArgs.Menu for information about menu item identification.
Example
The following code handles the GridView.PopupMenuShowing event to change predefined commands in the Data Grid’s Column Header Menu:
- Captions of the “Sort Ascending” and “Sort Descending” commands are replaced with custom strings.
- A few commands are hidden.
- Two “Best Fit” commands are disabled.
using DevExpress.Utils.Menu;
using DevExpress.XtraEditors;
using DevExpress.XtraGrid.Localization;
using DevExpress.XtraGrid.Views.Grid;
private void gridView1_PopupMenuShowing(object sender, PopupMenuShowingEventArgs e) {
if(e.MenuType == GridMenuType.Column) {
string sortAsc = "A to Z";
string sortDesc = "Z to A";
if (e.HitInfo.Column.ColumnType == typeof(DateTime)) {
sortAsc = "Old to New";
sortDesc = "New to Old";
}
DXMenuItem itemAsc = e.Menu.Find(GridStringId.MenuColumnSortAscending); // "Sort Ascending"
if (itemAsc != null)
itemAsc.Caption = sortAsc;
DXMenuItem itemDesc = e.Menu.Find(GridStringId.MenuColumnSortDescending); // "Sort Descending"
if (itemDesc != null)
itemDesc.Caption = sortDesc;
e.Menu.Hide(GridStringId.MenuFooterHide); //"Hide Footer"
e.Menu.Hide(GridStringId.MenuColumnFilterEditor); // "Filter Editor..."
e.Menu.Hide(GridStringId.MenuColumnFindFilterShow); // "Show Find Panel"
e.Menu.Hide(GridStringId.MenuColumnFindFilterHide); // "Hide Find Panel"
e.Menu.Hide(GridStringId.MenuColumnAutoFilterRowHide); // "Hide Auto Filter Row"
e.Menu.Hide(GridStringId.MenuColumnAutoFilterRowShow); // "Show Auto Filter Row"
DXMenuItem itemBestFit = e.Menu.Find(GridStringId.MenuColumnBestFit); // "Best Fit"
if (itemBestFit != null)
itemBestFit.Enabled = false;
DXMenuItem itemBestFitAll = e.Menu.Find(GridStringId.MenuColumnBestFitAllColumns); // "Best Fit All Columns"
if (itemBestFitAll != null)
itemBestFitAll.Enabled = false;
}
}
Add Custom Items to Built-In Menus
Handle the GridView.PopupMenuShowing event and add custom items to the event’s e.Menu.Items parameter. You can use the following objects as custom items:
- DXMenuItem - A regular button.
- DXSubMenuItem - A sub-menu.
- DXMenuCheckItem - A check button.
Example
The following example shows how to use the GridView.PopupMenuShowing event to create a custom menu in the Data Grid control. The created menu is displayed when you right-click within a data row or group row. It contains a ‘Rows’ submenu with a single “Delete this row” regular button, and a ‘Cell Merging’ check button.
A click on the ‘Delete this row’ button invokes the ColumnView.DeleteRow method. The ‘Cell Merging’ check button toggles the GridOptionsView.AllowCellMerge option.
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.Utils.Menu;
using DevExpress.XtraEditors;
private void gridView1_PopupMenuShowing(object sender, PopupMenuShowingEventArgs e) {
GridView view = sender as GridView;
if (e.MenuType == DevExpress.XtraGrid.Views.Grid.GridMenuType.Row) {
int rowHandle = e.HitInfo.RowHandle;
// Delete existing menu items, if any.
e.Menu.Items.Clear();
// Add the Rows submenu with the 'Delete Row' command
e.Menu.Items.Add(CreateSubMenuRows(view, rowHandle));
// Add the 'Cell Merging' check menu item.
DXMenuItem item = CreateMenuItemCellMerging(view, rowHandle);
item.BeginGroup = true;
e.Menu.Items.Add(item);
}
}
DXMenuItem CreateSubMenuRows(GridView view, int rowHandle) {
DXSubMenuItem subMenu = new DXSubMenuItem("Rows");
string deleteRowsCommandCaption;
if (view.IsGroupRow(rowHandle))
deleteRowsCommandCaption = "&Delete rows in this group";
else
deleteRowsCommandCaption = "&Delete this row";
DXMenuItem menuItemDeleteRow = new DXMenuItem(deleteRowsCommandCaption, new EventHandler(OnDeleteRowClick), imageCollection1.Images[0]);
menuItemDeleteRow.Tag = new RowInfo(view, rowHandle);
menuItemDeleteRow.Enabled = view.IsDataRow(rowHandle) || view.IsGroupRow(rowHandle);
subMenu.Items.Add(menuItemDeleteRow);
return subMenu;
}
DXMenuCheckItem CreateMenuItemCellMerging(GridView view, int rowHandle) {
DXMenuCheckItem checkItem = new DXMenuCheckItem("Cell &Merging",
view.OptionsView.AllowCellMerge, null, new EventHandler(OnCellMergingClick));
checkItem.Tag = new RowInfo(view, rowHandle);
checkItem.ImageOptions.Image = imageCollection1.Images[1];
return checkItem;
}
void OnDeleteRowClick(object sender, EventArgs e) {
DXMenuItem menuItem = sender as DXMenuItem;
RowInfo ri = menuItem.Tag as RowInfo;
if (ri != null) {
string message = menuItem.Caption.Replace("&", "");
if (XtraMessageBox.Show(message + " ?", "Confirm operation", MessageBoxButtons.YesNo) != DialogResult.Yes)
return;
ri.View.DeleteRow(ri.RowHandle);
}
}
void OnCellMergingClick(object sender, EventArgs e) {
DXMenuCheckItem item = sender as DXMenuCheckItem;
RowInfo info = item.Tag as RowInfo;
info.View.OptionsView.AllowCellMerge = item.Checked;
}
class RowInfo {
public RowInfo(GridView view, int rowHandle) {
this.RowHandle = rowHandle;
this.View = view;
}
public GridView View;
public int RowHandle;
}
Example
The following sample code handles the GridView.PopupMenuShowing event to customize the column header context menu before it is displayed. The code clears default menu items and adds a new command that locks a clicked column’s position.
using DevExpress.XtraGrid.Menu;
using DevExpress.Utils.Menu;
using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Views.Grid;
// ...
private void bandedGridView1_PopupMenuShowing(object sender, PopupMenuShowingEventArgs e) {
if(e.MenuType == GridMenuType.Column) {
GridViewColumnMenu menu = e.Menu as GridViewColumnMenu;
menu.Items.Clear();
if(menu.Column != null) {
menu.Items.Add(CreateCheckItem("Lock this column", menu.Column, null));
}
}
}
// Creates a menu item.
DXMenuCheckItem CreateCheckItem(string caption, GridColumn column, Image image) {
DXMenuCheckItem item = new DXMenuCheckItem(caption,
!column.OptionsColumn.AllowMove, image, new EventHandler(OnCanMoveItemClick));
item.Tag = new MenuColumnInfo(column);
return item;
}
// Menu item click handler.
void OnCanMoveItemClick(object sender, EventArgs e) {
DXMenuCheckItem item = sender as DXMenuCheckItem;
MenuColumnInfo info = item.Tag as MenuColumnInfo;
if(info == null) return;
info.Column.OptionsColumn.AllowMove = !item.Checked;
}
class MenuColumnInfo {
public MenuColumnInfo(GridColumn column) {
this.Column = column;
}
public GridColumn Column;
}
Change Menu Items’ Default Behavior
A click on a menu item in the built-in context menus raises the GridView.GridMenuItemClick event. After your event handler is complete, the grid performs the menu item’s related action by default. You can handle the GridMenuItemClick event to:
- Perform custom actions
- Prevent the default action from being invoked after your event handler is complete, by setting the event’s Handled parameter to true.
Example
The following example handles the GridView.GridMenuItemClick event to show a warning when you select the “Hide This Column” command from the column header menu. Pressing ‘No’ in the message box cancels the invoked action.
private void gridView1_GridMenuItemClick(object sender, DevExpress.XtraGrid.Views.Grid.GridMenuItemClickEventArgs e) {
if(e.MenuType == DevExpress.XtraGrid.Views.Grid.GridMenuType.Column) {
GridStringId value = e.DXMenuItem.Tag is GridStringId ? (GridStringId)e.DXMenuItem.Tag : 0 ;
if (value == GridStringId.MenuColumnRemoveColumn) { //"Hide This Column" command
if(MessageBox.Show("Do you want to hide this column?", "Warning", MessageBoxButtons.YesNo)== DialogResult.No) {
e.Handled = true; //Cancel further default processing
}
}
}
}
Show a Custom Popup Menu for Any Grid Element
You can create and show a custom context menu within a View’s BaseView.MouseDown event handler. When handling this event, identify the clicked element with the BaseView.CalcHitInfo method. This method returns information about a grid element at the specified screen point.
Use the GridViewMenu class to create a custom menu instance for Grid Views and Banded Grid Views. You can add the following menu item objects to the GridViewMenu.Items collection:
- DXMenuItem - a regular button.
- DXSubMenuItem - a sub-menu.
- DXMenuCheckItem - a check button.
Example
This example creates a custom context menu that is displayed on right-clicking the header panel button. This menu has two items: Columns and Runtime Column Customization. The first item is a sub menu that allows you to show/hide grid columns. The second item invokes the Customization Form.
private void gridView1_MouseDown(object sender, MouseEventArgs e) {
GridView view = sender as GridView;
if (e.Button == MouseButtons.Right)
DoShowMenu(view.CalcHitInfo(new Point(e.X, e.Y)));
}
void DoShowMenu(DevExpress.XtraGrid.Views.Grid.ViewInfo.GridHitInfo hi) {
DevExpress.XtraGrid.Menu.GridViewMenu menu = null;
// Check whether the header panel button has been clicked.
if (hi.HitTest == DevExpress.XtraGrid.Views.Grid.ViewInfo.GridHitTest.ColumnButton) {
menu = new GridViewColumnButtonMenu(hi.View);
menu.Init(hi);
menu.Show(hi.HitPoint);
}
}
public class GridViewColumnButtonMenu : GridViewMenu {
public GridViewColumnButtonMenu(DevExpress.XtraGrid.Views.Grid.GridView view) : base(view) { }
// This method is automatically called by the menu's public Init method.
protected override void CreateItems() {
Items.Clear();
DXSubMenuItem submenuColumns = new DXSubMenuItem("Columns");
Items.Add(submenuColumns);
Items.Add(CreateMenuItem("Runtime Column Customization", GridMenuImages.Column.Images[3], "Customization", true));
foreach (GridColumn column in View.Columns) {
if (column.OptionsColumn.ShowInCustomizationForm && column.GroupIndex<0) {
submenuColumns.Items.Add(CreateMenuCheckItem(column.GetCaption(), column.Visible, null, column, true));
}
}
}
protected override void OnMenuItemCheckedChanged(object sender, EventArgs e) {
DXMenuCheckItem item = sender as DXMenuCheckItem;
if (item.Tag is GridColumn) {
GridColumn column = item.Tag as GridColumn;
column.Visible = item.Checked;
}
}
protected override void OnMenuItemClick(object sender, EventArgs e) {
DXMenuItem item = sender as DXMenuItem;
if (item.Tag == null) return;
if (item.Tag.ToString() == "Customization") View.ShowCustomization();
}
}
Menu Appearance
By default, the Data Grid paints its menus according to the system settings, without taking into account the current skin.
To apply a skin to the Data Grid’s menus, place a BarManager or RibbonControl component onto the form. This component is automatically bound to the Data Grid’s EditorContainer.MenuManager property. The RibbonControl/BarManager now manages the display of the grid’s menus, and applies the selected paint scheme (skin) to them.
The following image shows a column header menu painted using different themes.
You can use the Project Settings Page or the DefaultLookAndFeel component to customize the default paint scheme for all controls, including the data grid’s popup menus.
Cheat Sheets and Best Practices
Read the following quick-reference guide for general information and examples: