Using a dropDownList in a RadGridView context menu

3 Answers 85 Views
ContextMenu GridView
Patgat
Top achievements
Rank 2
Iron
Iron
Iron
Patgat asked on 09 Jan 2023, 04:00 PM | edited on 09 Jan 2023, 04:01 PM

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

Sort by
0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 12 Jan 2023, 07:20 AM

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.

0
Patgat
Top achievements
Rank 2
Iron
Iron
Iron
answered on 12 Jan 2023, 06:25 PM

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

Dess | Tech Support Engineer, Principal
Telerik team
commented on 13 Jan 2023, 05:40 AM

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:

https://feedback.telerik.com/winforms/1579852-radcontextmenu-drop-down-is-not-closed-when-clicking-outside-the-popup 

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.

0
Patgat
Top achievements
Rank 2
Iron
Iron
Iron
answered on 13 Jan 2023, 01:44 PM

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

 

Dess | Tech Support Engineer, Principal
Telerik team
commented on 16 Jan 2023, 07:57 AM

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.

Patgat
Top achievements
Rank 2
Iron
Iron
Iron
commented on 20 Jan 2023, 02:36 PM

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

 

Dess | Tech Support Engineer, Principal
Telerik team
commented on 23 Jan 2023, 11:13 AM

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.

Patgat
Top achievements
Rank 2
Iron
Iron
Iron
commented on 24 Jan 2023, 11:04 AM

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

 

Dess | Tech Support Engineer, Principal
Telerik team
commented on 24 Jan 2023, 03:07 PM

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();
            } 
        }

 

Patgat
Top achievements
Rank 2
Iron
Iron
Iron
commented on 10 Feb 2023, 12:39 PM

Many thanks Dess, this works fine now.

Patrick

 

Tags
ContextMenu GridView
Asked by
Patgat
Top achievements
Rank 2
Iron
Iron
Iron
Answers by
Dess | Tech Support Engineer, Principal
Telerik team
Patgat
Top achievements
Rank 2
Iron
Iron
Iron
Share this question
or