How to select the newly added new item in GridviewComboBoxColumn (DropDown style)

8 posts, 0 answers
  1. sebastien
    sebastien avatar
    42 posts
    Member since:
    May 2017

    Posted 13 Nov 2019 Link to this post

    Hi,

    I want the user to be able to insert a new item in the combobox (via the underlying TextBoxEditor).

    When entered, the user should see the newly added item as selected in the combobox.

    I'm probably missing an event or not making the add/set DataSource at the good place.

    I'm doing everything in the CellEndEdit event handler of the grid.

     

    Reproduce: double-click on "Type 1", type any text and change the column.

    If you re-open the content of the combo, the new item is there

    public partial class RadForm1 : Telerik.WinControls.UI.RadForm
        {
            private List<KeyValuePair<string, string>> _list;
     
            public RadForm1()
            {
                InitializeComponent();
     
                this.Load += RadForm1_Load;
     
                radGridView1.CellEndEdit += RadGridView1_CellEndEdit;
            }
     
            private void RadForm1_Load(object sender, EventArgs e)
            {
                _list = new List<KeyValuePair<string, string>>();
     
                _list.Add(new KeyValuePair<string, string>(TestType.type_1.ToString(), "Type 1"));
                _list.Add(new KeyValuePair<string, string>(TestType.type_2.ToString(), "Type 2"));
                _list.Add(new KeyValuePair<string, string>(TestType.type_3.ToString(), "Type 3"));
     
                SetColumnDataset();
     
                LoadData();
            }
     
            private void SetColumnDataset()
            {
                var comboColumn = radGridView1.Columns["columnCombo"] as Telerik.WinControls.UI.GridViewComboBoxColumn;
                if (comboColumn != null)
                {
                    comboColumn.DropDownStyle = RadDropDownStyle.DropDown;
                    comboColumn.DataSource = _list;
                    comboColumn.DisplayMember = "Value"// name to show
                    comboColumn.ValueMember = "Key"// name of element of Guid of specific service
                }
            }
     
            private void LoadData()
            {
                radGridView1.Rows.Clear();
                GridViewDataRowInfo rowInfo = new GridViewDataRowInfo(this.radGridView1.MasterView);
                rowInfo.Cells["columnCombo"].Value = Guid.NewGuid().ToString();
                rowInfo.Cells["columnCombo"].Value = TestType.type_3.ToString();
                radGridView1.Rows.Add(rowInfo);
     
                rowInfo = new GridViewDataRowInfo(this.radGridView1.MasterView);
                rowInfo.Cells["columnCombo"].Value = Guid.NewGuid().ToString();
                rowInfo.Cells["columnCombo"].Value = TestType.type_1.ToString();
                radGridView1.Rows.Add(rowInfo);
            }
     
            void RadGridView1_CellEndEdit(object sender, GridViewCellEventArgs e)
            {
                // e.ActiveEditor.GetType()
                if (e.Column == radGridView1.Columns["columnCombo"])
                {
                    if (e.Value != null && e.Value.ToString() != String.Empty)
                    {
                        TestType enumVal;
                        bool isEnum = Enum.TryParse<TestType>(e.Value.ToString(), out enumVal);
                        if (isEnum)
                        {
                            // enumVal holds the value
                        }
                        else
                        {
                            AddNewColumnItem(Guid.NewGuid().ToString());
                        }
                    }
                    else
                    {
                        AddNewColumnItem(Guid.NewGuid().ToString());
                    }
                }
            }
     
            private void AddNewColumnItem(string name)
            {
                if (!_list.Any(x => x.Key == name))
                {
                    _list.Add(new KeyValuePair<string, string>(name, string.Format("Type {0}", name)));
                    SetColumnDataset();
                }
            }
        }
     
        public enum TestType
        {
            type_1,
            type_2,
            type_3
        }
  2. Dess | Tech Support Engineer, Sr.
    Admin
    Dess | Tech Support Engineer, Sr.  avatar
    3624 posts

    Posted 14 Nov 2019 Link to this post

    Hello, Sebastien, 

    The provided sample code snippet is greatly appreciated.

    Note that the GridViewComboBoxColumn accepts only valid values according to the applied DataSource to the column. If you enter any custom input (that doesn't match any record in the drop down items), it wouldn't be considered as valid. Hence, it won't be stored to the cell.

    If you need to allow the end-users to add custom values, it would be necessary this new value to be added to the DataSource collection that is applied to the column. Please refer to the following help article which demonstrates a sample approach: https://docs.telerik.com/devtools/winforms/controls/gridview/editors/how-to/allow-end-users-to-add-items-to-dropdownlisteditor

    However, if you type exactly the same text as one of the items that are available in the drop down, it is expected to be preserved in the cell. But it would be necessary to sync the selection in the editor with the entered text either via opening the drop down or by enabling the autocomplete functionality as follows: 

    this.radGridView1.CellEditorInitialized+=radGridView1_CellEditorInitialized;
    
    private void radGridView1_CellEditorInitialized(object sender, GridViewCellEventArgs e)
    {
        RadDropDownListEditor editor = e.ActiveEditor as RadDropDownListEditor;
        if (editor!=null)
        {
            RadDropDownListEditorElement el = editor.EditorElement as RadDropDownListEditorElement;
            el.AutoCompleteMode = AutoCompleteMode.Append; 
        }
    }


    Thus, if you enter edit mode (cell value = "Type 1"), don't open the drop down and just type "Type 2", it will be preserved as cell's value. 

    I hope this information helps. If you need any further assistance please don't hesitate to contact me.

    Regards,
    Dess | Tech Support Engineer, Sr.
    Progress Telerik

    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  3. sebastien
    sebastien avatar
    42 posts
    Member since:
    May 2017

    Posted 14 Nov 2019 in reply to Dess | Tech Support Engineer, Sr. Link to this post

    Thanks Dess,

    I managed to modify the test code but I'm still missing something, maybe only a refresh of the row or cell?

    double-click on "Type 1", type any text and change the column. The new typed item is not showned, but if you open the editor (double-click on the same cell), the new item is there AND is selected.

     

    Code:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using Telerik.WinControls;
    using Telerik.WinControls.UI;
     
    namespace TelerikWinFormsApp2
    {
        public partial class RadForm1 : Telerik.WinControls.UI.RadForm
        {
            public List<KeyValuePair<string, string>> _list;
     
            public RadGridView GridView
            {
                get { return radGridView1; }
            }
     
            public RadForm1()
            {
                InitializeComponent();
     
                this.Load += RadForm1_Load;
     
                radGridView1.EditorRequired += RadGridView1_EditorRequired;
                radGridView1.CellEditorInitialized += RadGridView1_CellEditorInitialized;
                radGridView1.CellEndEdit += RadGridView1_CellEndEdit;
            }
     
            private void RadGridView1_CellEndEdit(object sender, GridViewCellEventArgs e)
            {
                if (this.radGridView1.CurrentCell.Tag != null)
                {
                    this.radGridView1.CurrentCell.Value = this.radGridView1.CurrentCell.Tag;
                    this.radGridView1.CurrentCell.Tag = null;
                }
            }
     
            private void RadGridView1_CellEditorInitialized(object sender, GridViewCellEventArgs e)
            {
                RadDropDownListEditor editor = e.ActiveEditor as RadDropDownListEditor;
                if (editor != null)
                {
                    RadDropDownListEditorElement el = editor.EditorElement as RadDropDownListEditorElement;
                    el.AutoCompleteMode = AutoCompleteMode.Append;
                }
            }
     
            private void RadGridView1_EditorRequired(object sender, EditorRequiredEventArgs e)
            {
                if (e.EditorType == typeof(RadDropDownListEditor))
                {
                    e.Editor = new AllowEnd_usersAddItemsComboBoxEditor();
                }
            }
     
            private void RadForm1_Load(object sender, EventArgs e)
            {
                _list = new List<KeyValuePair<string, string>>();
     
                _list.Add(new KeyValuePair<string, string>(TestType.type_1.ToString(), "Type 1"));
                _list.Add(new KeyValuePair<string, string>(TestType.type_2.ToString(), "Type 2"));
                _list.Add(new KeyValuePair<string, string>(TestType.type_3.ToString(), "Type 3"));
     
                SetColumnDataset();
     
                LoadData();
            }
     
            private void SetColumnDataset()
            {
                var comboColumn = radGridView1.Columns["columnCombo"] as Telerik.WinControls.UI.GridViewComboBoxColumn;
                if (comboColumn != null)
                {
                    comboColumn.DropDownStyle = RadDropDownStyle.DropDown;
                    comboColumn.DataSource = _list;
                    comboColumn.DisplayMember = "Value"// name to show
                    comboColumn.ValueMember = "Key"// name of element of Guid of specific service
                }
            }
     
            private void LoadData()
            {
                radGridView1.Rows.Clear();
                GridViewDataRowInfo rowInfo = new GridViewDataRowInfo(this.radGridView1.MasterView);
                rowInfo.Cells["columnCombo"].Value = Guid.NewGuid().ToString();
                rowInfo.Cells["columnCombo"].Value = TestType.type_3.ToString();
                radGridView1.Rows.Add(rowInfo);
     
                rowInfo = new GridViewDataRowInfo(this.radGridView1.MasterView);
                rowInfo.Cells["columnCombo"].Value = Guid.NewGuid().ToString();
                rowInfo.Cells["columnCombo"].Value = TestType.type_1.ToString();
                radGridView1.Rows.Add(rowInfo);
            }
        }
     
        public enum TestType
        {
            type_1,
            type_2,
            type_3
        }
     
        public class AllowEnd_usersAddItemsComboBoxEditor : RadDropDownListEditor
        {
            public override bool EndEdit()
            {
                var textNewValue = ((RadDropDownListEditorElement)EditorElement).Text;
     
                if (string.IsNullOrEmpty(textNewValue))
                {
                    // allow null
                    return base.EndEdit();
                }
     
                GridComboBoxCellElement cellElement = this.OwnerElement as GridComboBoxCellElement;
                RadGridView grid = cellElement.GridControl;
                RadForm1 f = (RadForm1)grid.FindForm();
     
                for (int i = 0; i < f._list.Count; i++)
                {
                    if (f._list[i].Value == textNewValue)
                        return base.EndEdit();
                }
     
                var id = Guid.NewGuid().ToString();
                f._list.Add(new KeyValuePair<string, string>(id, textNewValue));
     
                f.GridView.CurrentRow.Cells["columnCombo"].Value = id;
     
                cellElement.Tag = id;
     
                return base.EndEdit();
            }
        }
    }
  4. Dess | Tech Support Engineer, Sr.
    Admin
    Dess | Tech Support Engineer, Sr.  avatar
    3624 posts

    Posted 15 Nov 2019 Link to this post

    Hello, Sebastien,

    I have updated the sample project using the latest code you provided. Indeed, the newly entered value is not displayed in the cell after exiting edit mode. However, the value is successfully added to the _list collection and stored in the cell. This is because you are using a List, not BindingList. BindingList implements the ListChanged event, which is raised when you add, remove, or set items. Bound controls listen to this event in order to know when to refresh their display.

    It is just necessary to replace this part of the code: 

    private List<KeyValuePair<string, string>> _list;
    
    // some other code
    
    _list = new List<KeyValuePair<string, string>>();

    with this:

     

    private BindingList<KeyValuePair<string, string>> _list;
    
    // some other code
    
    _list = new BindingList<KeyValuePair<string, string>>();

    Additional information is available in the following threads:

    https://stackoverflow.com/questions/2243950/listt-vs-bindinglistt-advantages-disadvantages 

    https://social.msdn.microsoft.com/Forums/vstudio/en-US/a7312df5-e336-43ea-8393-6ffd17fe1ac6/whats-the-diff-between-listt-and-bindinglistt?forum=csharpgeneral

    Should you have further questions please let me know.

    Regards,
    Dess | Tech Support Engineer, Sr.
    Progress Telerik

    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  5. sebastien
    sebastien avatar
    42 posts
    Member since:
    May 2017

    Posted 18 Nov 2019 in reply to Dess | Tech Support Engineer, Sr. Link to this post

    It worked on the test project, but I applied the same basics on the client's project and got an exception inside the new control.

    There is a NullException thrown in the "EndEdit" method, when I do the "retireCtl.RadGridView.CurrentRow.Cells["columnCombo"].Value = id;"

     

    Any idea? thanks

     

    Here's the stack trace:

    at Client.Parametrization.Windows.Forms.AssumptionsUI.AllowEnd_usersAddItemsComboBoxEditor.EndEdit() in C:\ACE\Versions\Dev\Sources\Client.Parametrization.Windows.Forms\AssumptionsUI\RetirementRates.cs:line 573
    at Telerik.WinControls.UI.GridViewEditManager.EndEditCore(Boolean validate, Boolean cancel)
    at Telerik.WinControls.UI.GridViewEditManager.OnPositionChanging(PositionChangingEventArgs args)
    at Telerik.WinControls.UI.GridViewEditManager.Telerik.WinControls.UI.IGridViewEventListener.PreProcessEvent(GridViewEvent eventData)
    at Telerik.WinControls.UI.GridViewEventProcessEntity.ProcessCollection(GridViewEvent gridEvent, PriorityWeakReferenceList list, GridEventProcessMode processMode)
    at Telerik.WinControls.UI.GridViewSynchronizationService.NotifyListeners(GridViewEvent gridEvent)
    at Telerik.WinControls.UI.GridViewSynchronizationService.FlushEvents()
    at Telerik.WinControls.UI.GridViewSynchronizationService.DispatchEvent(GridViewEvent gridEvent)
    at Telerik.WinControls.UI.GridViewSynchronizationService.RaiseCurrentChanged(GridViewTemplate template, GridViewRowInfo row, GridViewColumn column, Boolean user)
    at Telerik.WinControls.UI.BaseGridNavigator.SelectCore(GridViewRowInfo row, GridViewColumn column)
    at Telerik.WinControls.UI.BaseGridNavigator.SelectNextColumn()
    at Telerik.WinControls.UI.GridRowBehavior.ProcessTabKey(KeyEventArgs keys)
    at Telerik.WinControls.UI.BaseGridBehavior.ProcessKey(KeyEventArgs keys)
    at Telerik.WinControls.UI.RadGridView.ProcessDialogKey(Keys keyData)
    at System.Windows.Forms.TextBoxBase.ProcessDialogKey(Keys keyData)
    at System.Windows.Forms.Control.PreProcessMessage(Message& msg)
    at System.Windows.Forms.Control.PreProcessControlMessageInternal(Control target, Message& msg)
    at System.Windows.Forms.Application.ThreadContext.PreTranslateMessage(MSG& msg)
    at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
    at Client.ACEConfiguration.Program.Main(String[] args) in C:\ACE\Versions\Dev\Sources\Client.AceConfiguration\Program.cs:line 74
  6. sebastien
    sebastien avatar
    42 posts
    Member since:
    May 2017

    Posted 18 Nov 2019 Link to this post

    Forgot to put the code of my method:

     

    public class AllowEnd_usersAddItemsComboBoxEditor : RadDropDownListEditor
       {
           public override bool EndEdit()
           {
               var textNewValue = ((RadDropDownListEditorElement)EditorElement).Text;
     
               if (string.IsNullOrEmpty(textNewValue))
               {
                   // allow null
                   return base.EndEdit();
               }
     
               GridComboBoxCellElement cellElement = this.OwnerElement as GridComboBoxCellElement;
               RadGridView grid = cellElement.GridControl;
     
               Client.Parametrization.Windows.Forms.AssumptionsUI.RetirementRates retireCtl;
               Control tempCtl = grid.Parent;
     
               bool found = false;
               do
               {
                   found = tempCtl.GetType() == typeof(Client.Parametrization.Windows.Forms.AssumptionsUI.RetirementRates);
     
                   if (!found)
                   {
                       tempCtl = tempCtl.Parent;
                   }
               }
               while (!found);
     
               retireCtl = tempCtl as Client.Parametrization.Windows.Forms.AssumptionsUI.RetirementRates;
     
               for (int i = 0; i < retireCtl.ServiceMethods.Count; i++)
               {
                   if (retireCtl.ServiceMethods[i].Value == textNewValue)
                   {
                       return base.EndEdit();
                   }
               }
     
               var id = Guid.NewGuid().ToString();
               retireCtl.ServiceMethods.Add(new KeyValuePair<string, string>(id, textNewValue));
     
               retireCtl.RadGridView.CurrentRow.Cells["columnCombo"].Value = id;
     
               cellElement.Tag = id;
     
               return base.EndEdit();
           }
       }
  7. Dess | Tech Support Engineer, Sr.
    Admin
    Dess | Tech Support Engineer, Sr.  avatar
    3624 posts

    Posted 20 Nov 2019 Link to this post

    Hello, Sebastien,

    I suppose that the CurrentRow is null in your case. Another possibility is the cell with this column name to be missing somehow. That is why you obtain the error message. You need to check the CurrentRow and cell before using it and assigning a value to any cell. 

    The provided code snippet is greatly appreciated. However, when I copy and paste it in my sample project, I was unable to build it due to some missing implementation. Please refer to the attached zip file. Could you please specify the exact steps how to reproduce the problem? Feel free to modify it in a way to reproduce the experienced issue and get back to me with it so I can investigate the precise case. Thank you in advance. 

    I am looking forward to your reply.

    Regards,
    Dess | Tech Support Engineer, Sr.
    Progress Telerik

    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  8. sebastien
    sebastien avatar
    42 posts
    Member since:
    May 2017

    Posted 21 Nov 2019 in reply to Dess | Tech Support Engineer, Sr. Link to this post

    I don't know what I've done, but its working, was my fault for the last error.

     

    thank you Dess, like always : great help from you!

Back to Top