Hi all,
I wish to open a DropDown list in a context menu when a user right click on a GridView cell and handle the click event on an element of this DropDown list.
I am a bit lost between the GridView context menu documentation and the one specific to general context menus
I tried using the RadMenuComboItem (as described in this document) but the result is no satisfactory.
Would someone have a simple example on how to do this ?
Many thanks
Patrick
3 Answers, 1 is accepted
Hi, Patrick,
I have prepared a sample code snippet for your reference demonstrating how to add a RadMenuComboItem to the default context menu for RadGridView. When the menu is opened with right-clicking a cell, the combo item's popup is shown as well:
public RadForm1()
{
InitializeComponent();
this.radGridView1.ContextMenuOpening += radGridView1_ContextMenuOpening;
}
RadMenuComboItem comboItem;
private void radGridView1_ContextMenuOpening(object sender, ContextMenuOpeningEventArgs e)
{
comboItem = new RadMenuComboItem();
for (int i = 0; i < 5; i++)
{
comboItem.Items.Add("Item" + i);
}
comboItem.ComboBoxElement.SelectedIndexChanged += ComboBoxElement_SelectedIndexChanged;
e.ContextMenu.Items.Add(comboItem);
e.ContextMenu.PopupOpened -= ContextMenu_PopupOpened;
e.ContextMenu.PopupOpened += ContextMenu_PopupOpened;
}
private void ContextMenu_PopupOpened(object sender, EventArgs args)
{
comboItem.ComboBoxElement.ArrowButton.PerformClick();
}
private void ComboBoxElement_SelectedIndexChanged(object sender, Telerik.WinControls.UI.Data.PositionChangedEventArgs e)
{
RadListDataItem item = (sender as RadDropDownListElement).SelectedItem as RadListDataItem;
this.Text = item.Text;
}
I hope this information helps. If you need any further assistance please don't hesitate to contact me.
Regards,
Dess | Tech Support Engineer, Principal
Progress Telerik
Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.
Hi Dess,
many thanks for this. It works well.
However, I have a strange issue preventing me to fully test this.
As you can see on the attached pictures, the contextMenu do not close anymore when doing a left click or typing escape.
This is application wide and I can't find a clue for it. I created a new project from scratch and this doesn't happen in it.
Would you have any idea, do I have to close myself these menus ?
Thanks for your reply
Patrick
Hi, Patrick,
According to the provided screenshots, it wouldn't be east to determine what causes this undesired behavior. However, I suspect that you may have hit a known issue with the popups not closing. Here is the feedback item for your reference:
Note that it is reproduced only in .NET 6 project. A fix was introduced in R3 2022 SP1. So feel free to upgrade in order to benefit for the fix.
If this is not the case and you are still experiencing any further difficulties, I would kindly ask you to submit a support ticket from your Telerik account and provide a sample runnable project demonstrating the problem you are facing. Thus, we would be able to make an adequate analysis of the precise case and provide further assistance.
Hi Dess,
thanks for this very quick answer. This is effectively the know issue you mentioned, however in my case with R3 2022 SP2 (2022.3.1109) along with .NET 7. I reversed to .NET 6 and its working fine now.
Back to the initial issue, how can I only have the list in the context menu, without the text box itself wich is uneded as you can see in the attached video (by the way with a too small size) ?
Thanks
Patrick
It is possible to specify maximum width for the combo item:
RadMenuComboItem comboItem;
int width = 25;
private void radGridView1_ContextMenuOpening(object sender, ContextMenuOpeningEventArgs e)
{
comboItem = new RadMenuComboItem();
comboItem.ComboBoxElement.TextBox.TextBoxItem.MaxSize = new Size(width, width);
comboItem.ComboBoxElement.MaxSize = new Size(width, width);
comboItem.MaxSize= new Size(width, width);
comboItem.ComboBoxElement.DropDownMinSize = new Size(300, 20);
for (int i = 0; i < 5; i++)
{
comboItem.Items.Add("Item" + i);
}
comboItem.ComboBoxElement.SelectedIndexChanged += ComboBoxElement_SelectedIndexChanged;
e.ContextMenu.Items.Add(comboItem);
e.ContextMenu.PopupOpened -= ContextMenu_PopupOpened;
e.ContextMenu.PopupOpened += ContextMenu_PopupOpened;
}
You can also set the ComboBoxElement.TextBox.Visibility property to Collapsed to eliminate the input box and cursor as well.
Hi Dess,
thanks for your answer and example. However, I have another issue with the code below. I am handling the SelectedIndexChanged event.
However, as the contextMenu list I present to the user often contains only one line. In that case, wether the user click it or type escape, as there is no change of index, I get this kind of ghost empty contextMenu (see the video).
What should I handle for this and how ?
Here is my test code:
RadMenuComboItem comboItem;
RadDropDownMenu? contextMenu;
GridDataCellElement currentCell;
void gvLignesFacture_ContextMenuOpening(object sender, Telerik.WinControls.UI.ContextMenuOpeningEventArgs e)
{
var cell = e.ContextMenuProvider as GridDataCellElement;
if (cell == null ||
cell.ColumnIndex != colVariationIDLigneFacture ||
((GridViewDataColumn)cell.ColumnInfo).Name != "ProduitVariationID" ||
cell.RowInfo.Cells[colVariationIDLigneFacture].Value == null)
{
return;
}
currentCell = cell;
// Get data to display
string line = cell.RowInfo.Cells[ColNomUsuelLigneFacture].Value.ToString();
if (line == null) return;
(List<ProduitVariationDisplayModel>, List<string>) result = ProcessChangeOfFactureLine(line, cell.RowInfo);
if (result.Item1.Count > 0)
{
// Collapse all default menu entries
for (int i = 0; i < e.ContextMenu.Items.Count; i++)
{ e.ContextMenu.Items[i].Visibility = ElementVisibility.Collapsed; }
int width = 600;
int height = 20;
comboItem = new RadMenuComboItem();
comboItem.ComboBoxElement.Visibility = ElementVisibility.Collapsed;
comboItem.ComboBoxElement.MaxSize = new Size(width, height);
comboItem.ComboBoxElement.DropDownMinSize = new Size(width, height);
comboItem.ComboBoxElement.DataSource = result.Item1;
comboItem.ComboBoxElement.DataMember = "ProduitVariationID";
comboItem.ComboBoxElement.DisplayMember = "ComposedNomVariation";
comboItem.ComboBoxElement.SelectedIndexChanged += ComboBoxElement_SelectedIndexChanged;
e.ContextMenu.Items.Add(comboItem);
contextMenu = e.ContextMenu;
e.ContextMenu.PopupOpened -= ContextMenu_PopupOpened;
e.ContextMenu.PopupOpened += ContextMenu_PopupOpened;
}
}
private void ContextMenu_PopupOpened(object sender, EventArgs args)
{
comboItem.ComboBoxElement.ArrowButton.PerformClick();
}
private void ComboBoxElement_SelectedIndexChanged(object sender, Telerik.WinControls.UI.Data.PositionChangedEventArgs e)
{
if (sender is RadDropDownListElement rddl)
{
RadListDataItem item = rddl.SelectedItem as RadListDataItem;
ProduitVariationDisplayModel pvd = item.Value as ProduitVariationDisplayModel;
if (contextMenu != null && currentCell != null && pvd != null)
{
currentCell.Value = pvd.ProduitVariationID;
contextMenu.Hide();
contextMenu = null;
}
}
}
Thanks for your feedback
Patrick
Indeed, the SelectedIndexChanged event may not be fired if the drop down contains only 1 item and it is already selected. You can subscribe to the RadMenuComboItem.ComboBoxElement.PopupClosing event and get the SelectedItem:
private void radGridView1_ContextMenuOpening(object sender, ContextMenuOpeningEventArgs e)
{
comboItem = new RadMenuComboItem();
comboItem.ComboBoxElement.TextBox.Visibility = ElementVisibility.Collapsed;
comboItem.ComboBoxElement.TextBox.TextBoxItem.MaxSize = new Size(width, width);
comboItem.ComboBoxElement.MaxSize = new Size(width, width);
comboItem.MaxSize= new Size(width, width);
comboItem.ComboBoxElement.DropDownMinSize = new Size(300, 20);
for (int i = 0; i < 1; i++)
{
comboItem.Items.Add("Item" + i);
}
comboItem.ComboBoxElement.SelectedIndexChanged += ComboBoxElement_SelectedIndexChanged;
e.ContextMenu.Items.Add(comboItem);
e.ContextMenu.PopupOpened -= ContextMenu_PopupOpened;
e.ContextMenu.PopupOpened += ContextMenu_PopupOpened;
comboItem.ComboBoxElement.PopupClosing -= ComboBoxElement_PopupClosing;
comboItem.ComboBoxElement.PopupClosing += ComboBoxElement_PopupClosing;
}
private void ComboBoxElement_PopupClosing(object sender, RadPopupClosingEventArgs args)
{
RadDropDownListElement el = sender as RadDropDownListElement;
if (el!=null && el.SelectedItem!=null)
{
this.Text = el.SelectedItem.Text;
}
}
I hope this will fit your requirements.
Dess,
this doesn't work for me.
When the DropDownList open, the customer is able to either:
- select a different element in the list than the already selected one (if there is more than one)
- dismiss the pop-up (escape,...) or click the already selected one.
In all cases, this close the popup list, but not the context Menu.
Within the selected element handler,, to avoid the 'ghost context menu' (see images 1 & 2) I explicitely do :
contextMenu.Hide(); contextMenu = null;
However, I can't do that in the popupClosing event as it freeze the screen (I could maybe do it in the popupClosed event but can't find a valid signature to declare it).
Please, remember that I 'simply' want to open a 'context' dropDownList unsing a right click on a GridView Cell, but have here no use for the context menu itself (I do collapse all menu entries in the ContextMenuOpening Eventhandler).
So how to close this empty context ?
Thanks
Patrick
Hi, Patrick,
Please have in mind that the popup is expected to be closed automatically if the user selects a new item or click on the already selected one. However, if you want to close the entire context menu when an item from the combo item is selected, feel free to use the RadMenuComboItem.ComboBoxElement.PopupClosed event:
RadMenuComboItem comboItem;
int width = 25;
RadDropDownMenu contextMenu = null;
private void radGridView1_ContextMenuOpening(object sender, ContextMenuOpeningEventArgs e)
{
contextMenu = e.ContextMenu;
comboItem = new RadMenuComboItem();
comboItem.ComboBoxElement.TextBox.Visibility = ElementVisibility.Collapsed;
comboItem.ComboBoxElement.TextBox.TextBoxItem.MaxSize = new Size(width, width);
comboItem.ComboBoxElement.MaxSize = new Size(width, width);
comboItem.MaxSize= new Size(width, width);
comboItem.ComboBoxElement.DropDownMinSize = new Size(300, 20);
for (int i = 0; i < 1; i++)
{
comboItem.Items.Add("Item" + i);
}
comboItem.ComboBoxElement.SelectedIndexChanged += ComboBoxElement_SelectedIndexChanged;
e.ContextMenu.Items.Add(comboItem);
e.ContextMenu.PopupOpened -= ContextMenu_PopupOpened;
e.ContextMenu.PopupOpened += ContextMenu_PopupOpened;
comboItem.ComboBoxElement.PopupClosing -= ComboBoxElement_PopupClosing;
comboItem.ComboBoxElement.PopupClosing += ComboBoxElement_PopupClosing;
comboItem.ComboBoxElement.PopupClosed -= ComboBoxElement_PopupClosed;
comboItem.ComboBoxElement.PopupClosed += ComboBoxElement_PopupClosed;
}
private void ComboBoxElement_PopupClosing(object sender, RadPopupClosingEventArgs args)
{
RadDropDownListElement el = sender as RadDropDownListElement;
if (el!=null && el.SelectedItem!=null)
{
this.Text = el.SelectedItem.Text;
}
}
private void ComboBoxElement_PopupClosed(object sender, RadPopupClosedEventArgs args)
{
if (contextMenu!=null)
{
contextMenu.Hide();
}
}
Many thanks Dess, this works fine now.
Patrick