Selection Changed Event in DataGridComboBoxColumn - vb.net

I have a Data grid with DatagridComboBoxColumn , and i want to Fire Event SelectionChanged when user Select any thing From the ComboBox , Do Some operations ,
how can i do that any advice ,
thanks

You can handle your DataGridView's EditingControlShowing event and cast the editing control to the ComboBox being displayed and then wire up its SelectionChangeCommitted event. Use the SelectionChangeCommitted handler do you what you need to do.
See the sample code in the MSDN article I linked for details.
Two important notes:
Despite the MSDN article's sample code it's best to use the
ComboBox SelectionChangeCommitted event, as discussed here and in the
comments of the linked MSDN article.
If you have more than one DatagridComboBoxColumn in your
DataGridView you might want to determine which fired either your
EditingControlShowing or the ComboBox's SelectionChangeCommitted
event. You can do this by checking your DGV
CurrentCell.ColumnIndex property value.
I reworked the MSDN sample code a bit to show what I mean:
Private Sub DataGridView1_EditingControlShowing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
' Only for a DatagridComboBoxColumn at ColumnIndex 1.
If DataGridView1.CurrentCell.ColumnIndex = 1 Then
Dim combo As ComboBox = CType(e.Control, ComboBox)
If (combo IsNot Nothing) Then
' Remove an existing event-handler, if present, to avoid
' adding multiple handlers when the editing control is reused.
RemoveHandler combo.SelectionChangeCommitted, New EventHandler(AddressOf ComboBox_SelectionChangeCommitted)
' Add the event handler.
AddHandler combo.SelectionChangeCommitted, New EventHandler(AddressOf ComboBox_SelectionChangeCommitted)
End If
End If
End Sub
Private Sub ComboBox_SelectionChangeCommitted(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim combo As ComboBox = CType(sender, ComboBox)
Console.WriteLine("Row: {0}, Value: {1}", DataGridView1.CurrentCell.RowIndex, combo.SelectedItem)
End Sub

Related

VB.Net Datagridview combobox add a handler

I've spent a day trying to figure out how to solve my problem, which is identical to
this related unanswered question
On the first combobox, my code works fine, no problem. When I try to change the combobox it throws an error Null Reference Exception
This is my code:
Private Sub dgvSurveyQuestions_EditingControlShowing(ByVal sender As Object, ByVal e As DataGridViewEditingControlShowingEventArgs) Handles dgvSurveyQuestions.EditingControlShowing
Dim editingComboBox As ComboBox = TryCast(e.Control, ComboBox)
If Not editingComboBox Is Nothing Then
'Add the handle to your IndexChanged Event
RemoveHandler editingComboBox.SelectedIndexChanged, AddressOf editingComboBox_SelectedIndexChanged
AddHandler editingComboBox.SelectedIndexChanged, AddressOf editingComboBox_SelectedIndexChanged
End If
'Prevent this event from firing twice, as is normally the case.
'RemoveHandler dgvSurveyQuestions.EditingControlShowing, AddressOf dgvSurveyQuestions_EditingControlShowing
End Sub
Private Sub editingComboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
Dim editingComboBox As ComboBox = TryCast(sender, ComboBox)
If editingComboBox Is Nothing Then Exit Sub
'Show your Message Boxes
MessageBox.Show(editingComboBox.SelectedValue.ToString) ' throws error here
End Sub
I'm still working on a different workaround, like adding a handler while the datagridview is populated or whatever.. I don't even know if this is possible but I need to do this.
I'm really stuck here, can someone shed some light and advice me on what to do? Thanks
Simply check if editingComboBox.SelectedValue is Nothing.
The DataGridView reuses only one ComboBox instance, and internally resets the DataSource of the ComboBox when the user selects another ComboBox cell.
Then the event SelectedIndexChanged raises and SelectedValue will be Nothing at that time.

vb.net remove rowsadded event on datagridviewcombobox selection

i create combobox column on dgv and enabled the .allowusertoaddrows properties.
but everytime i dropdown combobox column, it always add new line or rows on my datagridview..
i've explore stackoverflow and google, but haven't found the solution yet..
but i've come to understanding that everytime dgv combobox column were clicked, it will automatically trigger default event to add new row.
how can i remove this handler
i've got reference from this link, but it didn't worked out for me..
please give me the solution, thanks you.
here's what i've tried
Private Sub dgv_beli_EditingControlShowing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles dgv_beli.EditingControlShowing
If dgv_beli.CurrentCell.ColumnIndex = 3 AndAlso TypeOf e.Control Is ComboBox Then
Dim comboBox As ComboBox = TryCast(e.Control, ComboBox)
RemoveHandler dgv_beli.EditingControlShowing, AddressOf dgv_beli_EditingControlShowing
End If
End Sub

How to handle both selected index change of combobox column and keypress event of text box column in datagridviw editingcontrolshowing event?

I have a datagridview in winform, in which four columns exists.Out of which 1 comboxcolumn and other three textboxcolumn. I have handeled combobox selected index change properly and it working fine. I handle this on Datagridview_editigControlShowing() event. Now i want to handle other three textboxes keyprees event so user can only enter numeric value. Now i searched on net there are some solution, but when i add another handler in editingControlShowing() method at run time when i click on combobox, it shows error.But when i remove the addHandler for textbox its worked fine.
My Code is look like
Private Sub dgvPurchase_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles dgvPurchase.EditingControlShowing
Dim editComboBox As ComboBox = TryCast(e.Control, ComboBox)
If Not editComboBox Is Nothing Then
AddHandler editComboBox.SelectedIndexChanged, AddressOf editComboBox_SelectedIndexChanged
End If
'RemoveHandler dgvPurchase.EditingControlShowing, AddressOf dgvPurchase_EditingControlShowing
End Sub
Now is there any way to handle both of these if so please provide me the solution

Handling all textbox event in one Handler

I do know how to handle event of textboxes in my form. But want to make this code shorter because I will 30 textboxes. It's inefficient to use this:
Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged, TextBox2.TextChanged, TextBox3.TextChanged, TextBox4.TextChanged, TextBox5.TextChanged, TextBox6.TextChanged, TextBox7.TextChanged, TextBox8.TextChanged, TextBox9.TextChanged, TextBox10.TextChanged
Dim tb As TextBox = CType(sender, TextBox)
Select Case tb.Name
Case "TextBox1"
MsgBox(tb.Text)
Case "TextBox2"
MsgBox(tb.Text)
End Select
End Sub
Is there a way to shorten the handler?
You can use Controls.OfType + AddHandler programmatically. For example:
Dim textBoxes = Me.Controls.OfType(Of TextBox)()
For Each txt In textBoxes
AddHandler txt.TextChanged, AddressOf txtTextChanged
Next
one handler for all:
Private Sub txtTextChanged(sender As Object, e As EventArgs)
Dim txt = DirectCast(sender, TextBox)
Select Case txt.Name
Case "TextBox1"
MsgBox(txt.Text)
Case "TextBox2"
MsgBox(txt.Text)
End Select
End Sub
If you have created very Textbox with the Designer, I don't think there is a better method.
But, if you have created the Textboxes dynamically, you should AddHandler in this way:
For i = 0 to 30
Dim TB as New Texbox
AddHandler TB.TextChanged, TextBox1_TextChanged
'Set every Property that you need
Me.Controls.Add(TB)
Next
Say If you are having that 30 textboxes inside a panel(PnlTextBoxes), Now you can create handler for your textboxes dynamically like this below
For each ctrl in PnlTextBoxes.controls
If TypeOf ctrl is TextBox then
AddHandler ctrl.TextChanged, AddressOf CommonClickHandler
end if
Next
Private Sub CommonHandler(ByVal sender As System.Object, _
ByVal e As System.EventArgs)
MsgBox(ctype(sender,TextBox).Text)
End Sub
The best way would be to inherit from TextBox, override its OnTextChanged method to add your custom handling code, and then use that on your form(s) instead of the built-in TextBox control.
That way, all of the event handling code is in one single place and you increase abstraction. The behavior follows and is defined within the control class itself, not the form that contains the control. And of course, it frees you from having a bunch of ugly, hard-to-maintain Handles statements, or worse, slow and even uglier For loops.
For example, add this code defining a new custom text box control to a new file in your project:
Public Class CustomTextBox : Inherits TextBox
Protected Overridable Sub OnTextChanged(e As EventArgs)
' Do whatever you want to do here...
MsgBox(Me.Text)
' Call the base class implementation for default behavior.
' (If you don't call this, the TextChanged event will never be raised!)
MyBase.OnTextChanged(e)
End Sub
End Class
Then, after you recompile, you should be able to replace your existing TextBox controls with the newly-defined CustomTextBox control that has all of your behavior built in.

EditingControlShowing events firing multiple times

I have a DGV in VB.Net 2008 connected to an Access DB table. The DGV is not Read Only, but is full of read-only columns except for one, which contains a combo box. The combo box allows the user to select an outcome for that particular row, and then the program copies in a pre calculated value into the "Profit" column depending upon the item selected in the combobox. Then the user hits the Save button and the DB updates (currently via SQL methods in the XSD).
Easy enough so far.
Here is the code.
Private Sub DGUserBets_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DGUserBets.EditingControlShowing
Dim combo As ComboBox = CType(e.Control, ComboBox)
If (combo IsNot Nothing) Then
// Remove an existing event-handler, if present, to avoid
// adding multiple handlers when the editing control is reused.
RemoveHandler combo.SelectedIndexChanged, _
New EventHandler(AddressOf DGUBStake_SelectedIndexChanged)
// Add the event handler.
AddHandler combo.SelectedIndexChanged, _
New EventHandler(AddressOf DGUBStake_SelectedIndexChanged)
End If
End Sub
Private Sub DGUBStake_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim myStatus As ComboBox = CType(sender, ComboBox)
Dim row = DGUserBets.CurrentRow
Select Case myStatus.SelectedIndex
Case 0
row.Cells("DGUBProfit").Value = 0
// pending. no action
Case 1
row.Cells("DGUBProfit").Value = row.Cells("DGUBIfWin").Value
// win
Case 2
// loses
row.Cells("DGUBProfit").Value = row.Cells("DGUBIfLose").Value
Case 3
// void
row.Cells("DGUBProfit").Value = 0
End Select
End Sub
The problem I have is that it would seem that if a user selects the desired outcome from the combobox but does NOT hit Enter, and simply mouses on to a different combobox to again select the outcome for a different row, the first eventhandler is not disconnected and thus the events fire multiple times. This then causes various default MsgBox errors and brings up problems when the user tries to commit all changes to the DB/exit program etc etc.
What do I need to do? Do I need to .EndEdit somewhere appropriate to force the row to save the changes? And where should I call this?
Thank you.
A quick glance at the code brings up this question:
If you create a new EventHandler when removing the existing one is it the same one?
I have had a similar issue, add a handler for CellLeave if the cell being exited is the cell you are looking for (IE e.ColumnIndex = myEditableColumn.Index) then call gv.EndEdit()
Also I would recommend making the handlers member variables for assignment and removal because it seems nicer then always saying Remove New and Add New.
CKRet/Quintin , thank you for the fast responses.
A quick try with this code seems better and breakpointing and stepping through the code seems to be firing the events correctly. I'm fairly new to .NET as the last real VB programming I did was VB6 so I'm not sure if this is the most elegant way to solve the problem.
Also a note that when LastEventHandler = Nothing, calling the RemoveHandler does not throw an exception, which is quite nice.
Maybe I should suggest to MS they should update that article.
Private Sub DGUserBets_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DGUserBets.EditingControlShowing
Dim combo As ComboBox = CType(e.Control, ComboBox)
Static LastEventHandler As EventHandler
If (combo IsNot Nothing) Then
// Remove an existing event-handler, if present, to avoid
// adding multiple handlers when the editing control is reused.
RemoveHandler combo.SelectedIndexChanged, _
LastEventHandler
LastEventHandler = New EventHandler(AddressOf DGUBStake_SelectedIndexChanged)
// Add the event handler.
AddHandler combo.SelectedIndexChanged, _
LastEventHandler
End If
End Sub
Simpler code which also appears to work well, as suggested by CKRet:
Dim combo As ComboBox = CType(e.Control, ComboBox)
If (combo IsNot Nothing) Then
RemoveHandler combo.SelectedIndexChanged, AddressOf DGUBStake_SelectedIndexChanged
AddHandler combo.SelectedIndexChanged, AddressOf DGUBStake_SelectedIndexChanged
End If
I know this is an archaic post, but after buggering around with this same problem for half a day I've found a way to solve this another way, so I thought it would be worth sharing.
Adding a second handler to handle the leave event of the combobox which then removes the handler of selectedvalue changed. Appears to work quite slick, and unlike another option i found gives the desired resulting action (unlike removing the value changed handler on the actual handling event which then won't fire if you re-select from the same combobox)
Private LastEventHandler As EventHandler = AddressOf Me.ComboBoxValueChanged
Private Sub dgvThisDatagrid_EditingControlShowing(sender As Object, e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles dgvOutstandingReminders.EditingControlShowing
If TypeOf (e.Control) Is ComboBox Then
Dim cboThisComboBox = DirectCast(e.Control, ComboBox)
AddHandler cboThisComboBox.SelectedValueChanged, LastEventHandler
AddHandler cboThisComboBox.Leave, AddressOf RemoveValueChangedHandler
End If
End Sub
Private Sub ComboBoxValueChanged(ByVal sender As Object, ByVal e As System.EventArgs)
If TypeOf (sender) Is ComboBox Then
Dim cboThisComboBox = DirectCast(sender, ComboBox)
MessageBox.Show("Value = " & cboThisComboBox.SelectedValue.ToString() & Environment.NewLine & "Text = " & cboThisComboBox.Text) ' Display index
End If
End Sub
Private Sub RemoveValueChangedHandler(ByVal sender As Object, ByVal e As System.EventArgs)
If TypeOf (sender) Is ComboBox Then
Dim cboThisCombobox = DirectCast(sender, ComboBox)
RemoveHandler cboThisCombobox.SelectedValueChanged, LastEventHandler
End If
End Sub