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
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
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.
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 >>
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";
}
}
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
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;
}
}
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.
Nikolay
the Telerik team