Capturing the combobox selected index changed, or any other way to know the value has been changed

9 posts, 1 answers
  1. Claude
    Claude avatar
    63 posts
    Member since:
    Apr 2009

    Posted 15 Sep 2011 Link to this post

    I need to know when the user has changed an entry in a combobox in a specific column (3, in this case), because I may need to adjust entries in another column to compensate.  The first method I tried was using the CellValueChanged event, which kind of works, but only fires after you select another grid element.  I need something that works immediately upon the value changing, but that accesses the new value.

    I found some other code on the forum to handle the selected index changed event, but had to modify it slightly:

    private void dataTransferRadGridView_CellBeginEdit(object sender, GridViewCellCancelEventArgs e)
            {
                try
                {
                    if (e.ColumnIndex == 3)
                    {
                        IInputEditor editor = this.dataTransferRadGridView.ActiveEditor;
                        if (editor != null)
                        {
                            if (editor.GetType() == typeof(RadDropDownListEditor))
                            {
                                RadDropDownListElement comboElement = (RadDropDownListElement)((RadDropDownListEditor)editor).EditorElement;
                                comboElement.SelectedIndexChanged += new Telerik.WinControls.UI.Data.PositionChangedEventHandler(comboElement_SelectedIndexChanged);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    string errorMessage = "Exception thrown in Main_MonitorConfiguration.dataTransferRadGridView_CellBeginEdit(object, GridViewCellCancelEventArgs)\nMessage: " + ex.Message;
                    LogMessage.LogError(errorMessage);
    #if DEBUG
                    MessageBox.Show(errorMessage);
    #endif
                }
            }
      
            private void dataTransferRadGridView_CellEndEdit(object sender, GridViewCellEventArgs e)
            {
                try
                {
                    if (e.ColumnIndex == 3)
                    {
                        IInputEditor editor = this.dataTransferRadGridView.ActiveEditor;
                        if (editor != null)
                        {
                            if (editor.GetType() == typeof(RadDropDownListEditor))
                            {
                                RadDropDownListElement comboElement = (RadDropDownListElement)((RadDropDownListEditor)editor).EditorElement;
                                comboElement.SelectedIndexChanged -= new Telerik.WinControls.UI.Data.PositionChangedEventHandler(comboElement_SelectedIndexChanged);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    string errorMessage = "Exception thrown in Main_MonitorConfiguration.dataTransferRadGridView_CellEndEdit(object, GridViewCellEventArgs)\nMessage: " + ex.Message;
                    LogMessage.LogError(errorMessage);
    #if DEBUG
                    MessageBox.Show(errorMessage);
    #endif
                }
            }
      
            void comboElement_SelectedIndexChanged(object sender, Telerik.WinControls.UI.Data.PositionChangedEventArgs e)
            {
                try
                {
                    int index = (int)(((RadDropDownListElement)sender).SelectedIndex);
                    if (index > -1)
                    {
                          
                        //// MessageBox.Show("Selected Index Changed. Value: " + index);
                        CorrectSlaveRegistersForAllRowEntries();
                    }
                }
                catch (Exception ex)
                {
                    string errorMessage = "Exception thrown in Main_MonitorConfiguration.dataTransferRadGridView_CellEndEdit(object, EventArgs-)\nMessage: " + ex.Message;
                    LogMessage.LogError(errorMessage);
    #if DEBUG
                    MessageBox.Show(errorMessage);
    #endif
                }
            }

    The major change I made was to replace all instances of RadComboBoxElement with RadDropDownListElement, and RadComboBoxEditor with RadDropDownListEditor, and use the appropriate event arguments.  The code would not compile otherwise.

    Original source is here.  I used the C# version, which you can see if you scroll down, as my starting point.

    Since one cannot tell which row fired the event, one has to correct every row entry.  However, the big problem is that the CellEndEdit event doesn't work.  The event is firing as expected, but the value of 'editor' always ends up being null.  So, I keep assigning new copies of the event to the handler, and none are ever removed.  The fact that the events aren't being removed when changing cells is a huge problem, because the event then fires for any cell selected, not just the ones in column 3.

    I'm not married to doing it this way.  All I need is some way to know that a new combobox element has been selected in a particular column, preferable also giving me the row was well, but it must give me some indication of what the new value is, either by knowing its text or by knowing its index in the combobox data set.

    Any suggestions will be appreciated.
  2. Emanuel Varga
    Emanuel Varga avatar
    1336 posts
    Member since:
    May 2010

    Posted 16 Sep 2011 Link to this post

    Hello Claude,

    A couple of comments here, please instead of using the CellBeginEdit event, please use the CellEditorInitialized event to register any events to a specific editor. Second, the grid reuses elements, so if you register, once, twice, 3 times, it fill fire 1,2,3 times and so on... please unregister before registering again so, always do -= handler and then += handler;

    After that, if you want to be notified for all cells value change, you should register the the ValueChanged event or the CellValueChanged event, the difference between the two being that the ValueChanged event fires every time the value for the cell has changed, against the CellValueChanged that fires after the user has moved from that cell (that cell looses focus).

    Hope this clarifies a few things for you, if you have any other problems please let me know.

    Best Regards,
    Emanuel Varga
  3. UI for WinForms is Visual Studio 2017 Ready
  4. Claude
    Claude avatar
    63 posts
    Member since:
    Apr 2009

    Posted 18 Sep 2011 Link to this post

    Thank you for your input, Emanuel.  It helped me get further along.

    I had already tried the CellValueChanged event, and it doesn't fire early enough for me.  I tried to use the ValueChanged event, and had the same problem.  It fires after the user has selected a new value from the DropDownList (RadComboBox), but before that value has been written to the appropriate cell in the grid.  Therefore I cannot tell what the new value will be at the time I need to apply corrections to values in another column.

    Using your suggestions, I came up with the following code, which almost works.  I think all variable types are hinted at by the code.

    private void dataTransferRadGridView_CellEditorInitialized(object sender, GridViewCellEventArgs e)
            {
                try
                {
                    string monitorType;
                    {
                        var editor = e.ActiveEditor as RadDropDownListEditor;
                        if (editor != null)
                        {
                            var editorElement = editor.EditorElement as RadDropDownListEditorElement;
                            if (editorElement != null)
                            {
                                editorElement.SelectedIndexChanged -= new Telerik.WinControls.UI.Data.PositionChangedEventHandler(editorElement_SelectedIndexChanged);
                                // we're only interested in changing the slave device register entries dynamically
                                if (e.ColumnIndex == 5)
                                {
                                    monitorType = e.Row.Cells[3].Value.ToString().Trim().Substring(0, 3);
      
                                    if (monitorType.CompareTo("BHM") == 0)
                                    {
                                        editorElement.DataSource = ConversionMethods.ConvertListOfStringsToArrayOfStrings(this.bhmDynamicsSlaveRegisterNames);
                                        e.Row.Cells[5].Value = CorrectSlaveRegisterNameIfNecessary(this.bhmDynamicsSlaveRegisterNames, e.Row.Cells[5].Value.ToString());
                                        editorElement.SelectedIndex = this.bhmDynamicsSlaveRegisterNames.IndexOf(e.Row.Cells[5].Value.ToString());
                                    }
                                    else if (monitorType.CompareTo("PDM") == 0)
                                    {
                                        editorElement.DataSource = ConversionMethods.ConvertListOfStringsToArrayOfStrings(this.pdmDynamicsSlaveRegisterNames);
                                        editorElement.SelectedIndex = this.pdmDynamicsSlaveRegisterNames.IndexOf(e.Row.Cells[5].Value.ToString()); ;
                                    }
                                }
                                else if (e.ColumnIndex == 3)
                                {
                                    editorElement.SelectedIndexChanged += new Telerik.WinControls.UI.Data.PositionChangedEventHandler(editorElement_SelectedIndexChanged);
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    string errorMessage = "Exception thrown in Main_MonitorConfiguration.dataTransferRadGridView_CellEditorInitialized(object, GridViewCellEventArgs)\nMessage: " + ex.Message;
                    LogMessage.LogError(errorMessage);
    #if DEBUG
                    MessageBox.Show(errorMessage);
    #endif
                }
            }
      
    void editorElement_SelectedIndexChanged(object sender, Telerik.WinControls.UI.Data.PositionChangedEventArgs e)
            {
                try
                {
                    int index = (int)(((RadDropDownListElement)sender).SelectedIndex);
                    if (index > -1)
                    {
                        CorrectSlaveRegistersForCurrentRow(index);
                    }
                }
                catch (Exception ex)
                {
                    string errorMessage = "Exception thrown in Main_MonitorConfiguration.editorElement_SelectedIndexChanged(object, Telerik.WinControls.UI.Data.PositionChangedEventArgs)\nMessage: " + ex.Message;
                    LogMessage.LogError(errorMessage);
    #if DEBUG
                    MessageBox.Show(errorMessage);
    #endif
                }
            }

    Here is the function I'm using to correct values.  I'm not sure if it's relevant to this discussion.  I know it's full of values that aren't obvious.  monitorUniqueNames is a List<string>.

    private void CorrectSlaveRegistersForCurrentRow(int selectedIndex)
            {
                try
                {
                    string monitorUniqueName;
                    string monitorType;
                    string modBusAddress = string.Empty;
                    GridViewRowInfo rowInfo;
                    if (this.dataTransferRadGridView != null)
                    {
                        if (this.dataTransferRadGridView.ColumnCount > 5)
                        {
                            rowInfo = this.dataTransferRadGridView.CurrentRow;
                            monitorUniqueName = rowInfo.Cells[3].Value.ToString().Trim();
                            monitorUniqueName = this.monitorUniqueNames[selectedIndex];
      
                            monitorType = monitorUniqueName.Substring(0, 3);
                            if (this.monitorsByUniqueMonitorName.ContainsKey(monitorUniqueName))
                            
                                modBusAddress = this.monitorsByUniqueMonitorName[monitorUniqueName].ModbusAddress.Trim();
                            }
                            else
                            {
                                modBusAddress = string.Empty;
                            }
      
                            rowInfo.Cells[4].Value = modBusAddress;
      
                            if (monitorType.CompareTo("BHM") == 0)
                            
                                        // if the current value in the cell is not appropriate, fix it
                                rowInfo.Cells[5].Value = CorrectSlaveRegisterNameIfNecessary(this.bhmDynamicsSlaveRegisterNames, rowInfo.Cells[5].Value.ToString());
                            }
                        }
                        else
                        {
                            string errorMessage = "Error in Main_MonitorConfiguration.CorrectSlaveRegistersForCurrentRow(int)\nThere were not enough columns declared in this.dataTransferRadGridView.";
                            LogMessage.LogError(errorMessage);
    #if DEBUG
                            MessageBox.Show(errorMessage);
    #endif
                        }
                    }
                    else
                    {
                        string errorMessage = "Error in Main_MonitorConfiguration.CorrectSlaveRegistersForCurrentRow(int)\nthis.dataTransferRadGridView was null.";
                        LogMessage.LogError(errorMessage);
    #if DEBUG
                        MessageBox.Show(errorMessage);
    #endif
                    }
                }
                catch (Exception ex)
                {
                    string errorMessage = "Exception thrown in Main_MonitorConfiguration.CorrectSlaveRegistersForCurrentRow(int)\nMessage: " + ex.Message;
                    LogMessage.LogError(errorMessage);
    #if DEBUG
                    MessageBox.Show(errorMessage);
    #endif
                }
            }


    Note that I only want to monitor the SelectedIndexChanged event for column 3.  I left in my code for setting a new DataSource for items in column 5, just in case it might cause a conflict for some reason.

    If I just stick to changing values in column 3, this works fine.  The selected index already refers to the new value, even though it hasn't yet been written to the appropriate grid cell.

    The problem is that when I click on an item in column 5, which is also a RadComboBoxColumn, the SelectedIndexChanged event fires before the CellEditorInitialized event can remove the event handler.  This confuses my code, because it expects that the SelectedIndexChanged event only fires for a change in column 3.  I cannot see any obvious way to either remove the event before it fires when I change cells, or to determine which column I'm in when inside the SelectedIndexChanged handler.  I am hoping someone knows a good way. 

    I think a hacky way would be to just get the current column and examine the entries in the cells.  Since the entries in column 3 and any other column in the grid have no overlap in values, that would determine which column is selected.  I haven't tried that yet, so I don't know if it will work.  It also isn't a general solution, which would be better for someone else who might have a similar problem.

    Again, any suggestions will be appreciated.
  5. Answer
    Alexander
    Admin
    Alexander avatar
    306 posts

    Posted 21 Sep 2011 Link to this post

    Hello Claude,

    Thank you for your question.

    You can check the CurrentColumn of RadGridView in the SelectedIndexChanged event handler and process your logic only for the required columns:
    private void editorElement_SelectedIndexChanged(object sender, Telerik.WinControls.UI.Data.PositionChangedEventArgs e)
    {
        if (this.radGridView1.CurrentColumn.Index == 3)
        {
            // process your logic
        }
    }

    I hope it helps you to achieve your scenario.

    Best regards,
    Alexander
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  6. Claude
    Claude avatar
    63 posts
    Member since:
    Apr 2009

    Posted 22 Sep 2011 Link to this post

    Thanks.  That should take care of it.
  7. s_athaulla
    s_athaulla avatar
    5 posts
    Member since:
    Aug 2006

    Posted 16 Sep 2012 Link to this post

    Hi,

    In SelectedIndexChanged event, i can get value and index of the Combo box in Grid, but how to assign other column values in the same row based on selected value?

    I am trying with below code, when try to assign value to the column in the same row, it is showing error "Nullreference Expetion unhandled". Please help anybody on the same

    private void editorElement_SelectedIndexChanged(object sender, Telerik.WinControls.UI.Data.PositionChangedEventArgs e)
            {
                if (this.Grid.CurrentColumn.Index == 2)
                {


                    //Grid.MasterTemplate.Rows[1].Cells["UOM"].Value = 1;
                    RadDropDownListElement comboBox1 = (RadDropDownListElement)sender;
                    // Display index
                    MessageBox.Show(comboBox1.SelectedIndex.ToString());
                    // Display value
                    MessageBox.Show(comboBox1.Text);
                    GridViewDataRowInfo dataRow = this.Grid.GridViewElement.GridControl.CurrentRow as GridViewDataRowInfo;
                    dataRow.Cells["ItemID"].Value = "1";
                }
                
            }


  8. Nikolay
    Admin
    Nikolay avatar
    1804 posts

    Posted 18 Sep 2012 Link to this post

    Hello s_athaulla,

    I am not sure which line exactly throws the exception. Generally speaking, the currently edited row is the CurrentRow, so instead of the commented row and the other row that you have for accessing the current row, you can directly use something like:

    this.radGridView1.CurrentRow.Cells["ItemID"].Value

    Please note that the cell is being indexed by the Name of the column in which it lies, so passing a wrong string may cause the described exception.

    If this tip does not help, I would kindly ask you to open a new support ticket and send a sample project which reproduces the wrong behavior. This will allow us to investigate what actually happens, hence we will be able to assist you further with adequate suggestions.Greetings,
    Nikolay
    the Telerik team
    RadControls for WinForms Q2'12 release is now live! Check out what's new or download a free trial >>
  9. s_athaulla
    s_athaulla avatar
    5 posts
    Member since:
    Aug 2006

    Posted 19 Sep 2012 Link to this post

    Hi,

    The Solutions what you given doesnot work, When we are assigning value to other columns in a row, it is throwing Nullvalueexception, Please look at below my code and correct. My aim is to assign values to Item ID, UOM and Qty on particular row after selecting value from Item Name Combobox column..

    private void frmPurchaseDetail_Load(object sender, EventArgs e)
            {
                conn = new SqlConnection(Program.cnstr);
                conn.Open();


                


                da = new SqlDataAdapter("SELECT ItemID, ItemName, UOM FROM MaterialMaster order by ItemName", conn);
                ds = new DataSet();


                da.Fill(ds);
                da.FillSchema(ds, SchemaType.Source, "MaterialMaster");
                da.Fill(ds, "MaterialMaster");
                //Grid.DataSource = ds.Tables["MaterialMaster"];


                GridViewDecimalColumn decimalColumn3 = new GridViewDecimalColumn();
                decimalColumn3.FieldName = "SerialNumber";
                decimalColumn3.HeaderText = "Sl. No.";
                this.Grid.Columns.Add(decimalColumn3);


                GridViewTextBoxColumn col = new GridViewTextBoxColumn();
                //col.DisplayMember = "ItemID";
                //col.ValueMember = "ItemID";
                //col.FieldName = "ItemID";
                //col.AllowFiltering = true;            
                //col.AllowSort = true;
                //col.SortOrder = RadSortOrder.Ascending;
                //col.HeaderText = "Item Code";
                //col.DataSource = ds.Tables["MaterialMaster"];            
                this.Grid.Columns.Add(col);


                GridViewComboBoxColumn col5 = new GridViewComboBoxColumn();
                col5.DisplayMember = "ItemName";
                col5.ValueMember = "ItemName";
                col5.FieldName = "ItemName";
                col5.HeaderText = "ItemName";
                col5.AllowSort = true;
                col5.AllowFiltering = true;            
                col5.DataSource = ds.Tables["MaterialMaster"];
                col5.SortOrder = RadSortOrder.Ascending;
                this.Grid.Columns.Add(col5);






                GridViewTextBoxColumn col2 = new GridViewTextBoxColumn();
                
                this.Grid.Columns.Add(col2);


                this.Grid.CellBeginEdit += new GridViewCellCancelEventHandler(Grid_CellBeginEdit);


                


                GridViewDecimalColumn decimalColumn = new GridViewDecimalColumn();
                decimalColumn.FieldName = "Quantity";
                decimalColumn.HeaderText = "Qty";
                this.Grid.Columns.Add(decimalColumn);


                GridViewDecimalColumn decimalColumn1 = new GridViewDecimalColumn();
                decimalColumn1.FieldName = "Cost";
                decimalColumn1.HeaderText = "Cost";
                this.Grid.Columns.Add(decimalColumn1);


                GridViewDecimalColumn decimalColumn2 = new GridViewDecimalColumn();
                decimalColumn2.FieldName = "Amount";
                decimalColumn2.HeaderText = "Amount";
                this.Grid.Columns.Add(decimalColumn2);


                GridViewTextBoxColumn textBoxColumn2 = new GridViewTextBoxColumn();
                textBoxColumn2.FieldName = "Remarks";
                textBoxColumn2.HeaderText = "Remarks";
                this.Grid.Columns.Add(textBoxColumn2);


                this.Grid.Columns["Amount"].Expression = "ROUND(Quantity * Cost)";


                this.Grid.Columns[0].Width = 40;
                this.Grid.Columns[0].ReadOnly = true;
                
                int i;
                for (i = 1; i <= 7; i++)
                {
                    this.Grid.Columns[i].Width = 100;
                }
                this.Grid.Columns[2].Width = 150;
                this.Grid.Columns[7].Width = 200;


                this.Grid.AllowAddNewRow = true;
                this.Grid.AllowDeleteRow = true;
                this.Grid.AllowEditRow = true;
                this.Grid.AddNewRowPosition = SystemRowPosition.Bottom; 
                
                this.Grid.EnableFiltering = false;
                this.Grid.ShowFilteringRow = false;
                this.Grid.ShowHeaderCellButtons = true;


                ds1 = new DataSet();
                da1 = new SqlDataAdapter("SELECT PaymentTerms FROM PaymentTerms", conn);
                da1.FillSchema(ds1, SchemaType.Source, "PaymentTerms");
                da1.Fill(ds1, "PaymentTerms");
                PaymentTerms.DataSource = ds1.Tables["PaymentTerms"];
                PaymentTerms.DisplayMember = "PaymentTerms";
                PaymentTerms.ValueMember = "PaymentTerms";


                ds1 = new DataSet();
                da1 = new SqlDataAdapter("SELECT SupplierCode, SupplierName FROM SupplierMaster", conn);
                da1.FillSchema(ds1, SchemaType.Source, "SupplierMaster");
                da1.Fill(ds1, "SupplierMaster");
                Supplier.DataSource = ds1.Tables["SupplierMaster"];
                Supplier.DisplayMember = "SupplierName";
                Supplier.ValueMember = "SupplierCode";


               
                GridViewSummaryItem summaryItem = new GridViewSummaryItem("Amount", "Total = {0}", GridAggregateFunction.Sum);
                GridViewSummaryRowItem summaryRowItem = new GridViewSummaryRowItem();
                summaryRowItem.Add(summaryItem);


                this.Grid.SummaryRowsBottom.Add(summaryRowItem);


                
                SqlCommand command = new SqlCommand("SELECT Max(PurchaseNumber) as PO FROM PurchaseMaster", conn);


                // Open the connection


                // Get the data reader
                SqlDataReader reader = command.ExecuteReader();
                int po;
                // Process each result
                while (reader.Read())
                {
                    po = Convert.ToInt32(reader["PO"]);
                    po++;
                    PurchaseNumber.Text=po.ToString();
                }


                // Close the reader and the connection
                reader.Close();
                conn.Close();


            }


            void Grid_CellEditorInitialized(object sender, GridViewCellEventArgs e)
            {
                try
                {
                    string monitorType;


                    {
                        var editor = e.ActiveEditor as RadDropDownListEditor;
                        if (editor != null)
                        {
                            var editorElement = editor.EditorElement as RadDropDownListEditorElement;
                            if (editorElement != null)
                            {
                                editorElement.SelectedValueChanged -= new Telerik.WinControls.UI.Data.ValueChangedEventHandler(editorElement_SelectedValueChanged);
                                // we're only interested in changing the slave device register entries dynamically
                                if (e.ColumnIndex == 2)
                                {
                                    editorElement.SelectedValueChanged += new Telerik.WinControls.UI.Data.ValueChangedEventHandler(editorElement_SelectedValueChanged);
                                    f = 0;
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    string errorMessage = "Exception thrown in Main_MonitorConfiguration.dataTransferRadGridView_CellEditorInitialized(object, GridViewCellEventArgs)\nMessage: " + ex.Message;
                    
                    MessageBox.Show(errorMessage);


                }
            }


            private void Grid_CellBeginEdit(object sender, GridViewCellCancelEventArgs e)
            {
                if (this.Grid.ActiveEditor != null) 
                {
                   
                 }
            }


            private void Grid_UserAddedRow(object sender, GridViewRowEventArgs e)
            {
                int i;


                for (i = 0; i < Grid.RowCount; i++)
                {
                    GridViewRowInfo CurrentRow = Grid.Rows[i];
                    CurrentRow.Cells[0].Value = i + 1;
                    
                }


            }


            private void Grid_CellValueChanged(object sender, GridViewCellEventArgs e)
            {
                this.Grid.Columns["Amount"].Expression = "ROUND((Quantity * Cost))";
                GridViewDataRowInfo dataRow = this.Grid.GridViewElement.GridControl.CurrentRow as GridViewDataRowInfo;
                
            }




            private void editorElement_SelectedValueChanged(object sender, Telerik.WinControls.UI.Data.ValueChangedEventArgs e)
            {
                if (this.Grid.CurrentColumn.Index == 2 )
                {


                    //Grid.MasterTemplate.Rows[1].Cells["UOM"].Value = 1;
                    RadDropDownListElement comboBox1 = (RadDropDownListElement)sender;
                    // Display index
                    //MessageBox.Show(comboBox1.SelectedIndex.ToString());
                    // Display value
                    MessageBox.Show(comboBox1.Text);
                    
                    this.Grid.CurrentRow.Cells["ItemID"].Value = "100000";
                    f = 1;


                }
                
            }

  10. Nikolay
    Admin
    Nikolay avatar
    1804 posts

    Posted 19 Sep 2012 Link to this post

    Hello s_athaulla,

    I would assume that RadGridView contains only the columns that you add manually. In that case, the exception is expected, because none of the columns has the Name ItemID. So, please make sure that such a column exists in the RadGridView when you are trying to access it.

    Once again, if you continue to experience the issue, please open a new support ticket and send me a compilable sample project that demonstrates the exception. This will allow me to look into your case in depth, hence provide you with a more helpful response.

    In future, please use the code formatting feature of the text editor when pasting code. This will allow us and the others interested in the case to review the code more easily.

    Thank you for your cooperation.

    Kind regards,
    Nikolay
    the Telerik team
    RadControls for WinForms Q2'12 release is now live! Check out what's new or download a free trial >>
Back to Top
UI for WinForms is Visual Studio 2017 Ready