This is a migrated thread and some comments may be shown as answers.

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

8 Answers 1200 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Claude
Top achievements
Rank 1
Claude asked on 16 Sep 2011, 01:34 AM
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.

8 Answers, 1 is accepted

Sort by
0
Emanuel Varga
Top achievements
Rank 1
answered on 16 Sep 2011, 07:12 AM
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
0
Claude
Top achievements
Rank 1
answered on 18 Sep 2011, 06:22 AM
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.
0
Accepted
Alexander
Telerik team
answered on 21 Sep 2011, 11:10 AM
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 >>

0
Claude
Top achievements
Rank 1
answered on 23 Sep 2011, 04:21 AM
Thanks.  That should take care of it.
0
s_athaulla
Top achievements
Rank 1
answered on 17 Sep 2012, 01:20 AM
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";
            }
            
        }


0
Nikolay
Telerik team
answered on 18 Sep 2012, 08:47 AM
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 >>
0
s_athaulla
Top achievements
Rank 1
answered on 19 Sep 2012, 09:48 AM
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;


            }
            
        }

0
Nikolay
Telerik team
answered on 19 Sep 2012, 04:02 PM
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 >>
Tags
GridView
Asked by
Claude
Top achievements
Rank 1
Answers by
Emanuel Varga
Top achievements
Rank 1
Claude
Top achievements
Rank 1
Alexander
Telerik team
s_athaulla
Top achievements
Rank 1
Nikolay
Telerik team
Share this question
or