I am using vb.net and winforms.
I have a Form with a Bound DataGridView. On the DGV I have 5 columns with ComboBox. I am using the EditingControlShowing Even to catch the ComboBox Selection. (see code bellow).
Here is the problem:
After I click on a Cell with a ComboBox and make a Selection and then update the underlying cell (cell = selected value) and then click on another Row of the DGV it goes haywire. If after I update the Cell I do and EndEdit on the corresponding row of the DataSource it seems to work find.
How can I determine whe corresponding Data Source row so that I can automate this?
Private Sub dataGridView1_EditingControlShowing(ByVal sender As Object, ByVal e As DataGridViewEditingControlShowingEventArgs) _
Handles DataGridView1.EditingControlShowing
Try
Debug.Print("entered the EditingControlShowing")
Dim ColName As String = Me.DataGridView1.Columns(Me.DataGridView1.CurrentCell.ColumnIndex).Name
If ColName = "Col1" Then 'Or ColName = "Col2" Or ColName = "Col3" Or ColName = "Col4" Or ColName = "Col5" Then
'the column you want to cast
Dim cmb As ComboBox = TryCast(e.Control, ComboBox)
RemoveHandler cmb.SelectedIndexChanged, AddressOf cmb_SelectedIndexChanged
AddHandler cmb.SelectedIndexChanged, AddressOf cmb_SelectedIndexChanged
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Sub cmb_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
Try
Me.DataGridView1.Rows(Me.DataGridView1.CurrentRow.Index).Cells(Me.DataGridView1.CurrentCell.ColumnIndex).Value = CType(sender, ComboBox).SelectedItem
'
' HERE IF I PUT MyDataSet.Tables(0).Rows(?).EndEding it works - but how to konw what row?
'
UpdateAvgColumn(Me.DataGridView1.CurrentRow.Index)
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
The events being fired are reentering. If you are currently processing an event, you have to be careful not to process other events. You have to put IF statements around the processing of the events to skip executing the code, if a different event is being processed.
sub dgv_selecteditemchanged()
If not processing_event
processing_event = true
...
processing_event = false
end if
end sub
Related
my datagridview name is "DG" and i add combobox column programatically named item as shown in code below.i want to create the event which call on itemchanged of combobox.i use DG_CellLeave event but it not call after the item selection immediatly but call when we leave the cell.i want to create event which immediatly call on selection change event of combobox.
Dim item As New DataGridViewComboBoxColumn
item.DataSource = dset.Tables("tab")
item.HeaderText = "item"
item.Name = "item"
item.DisplayMember = "p_name"
item.DataPropertyName = "item"
DG.Columns.Add(item)
which event should i choose for this purpose...
You should take a look at: DataGridView.EditingControlShowing Event. This event is raised whenever an edit control is shown in the DataGridView. It can be handled/used like below:
Dim gridComboBox As ComboBox
Private Sub DG_EditControlShowing(sender As Object, e As DataGridViewEditingControlShowingEventArgs)
' Check to see if the ColumnIndex is where we expect to have the DropDown
If (DG.CurrentCell.ColumnIndex = 1) Then
' Get the ComboBox that is being shown
gridComboBox = TryCast(e.Control, ComboBox)
If Not (gridComboBox Is Nothing) Then
' Always remove the Event Handler before Adding, when setting them at runtime
RemoveHandler gridComboBox.SelectedIndexChanged, AddressOf gridComboBox_SelectedIndexChanged
AddHandler gridComboBox.SelectedIndexChanged, AddressOf gridComboBox_SelectedIndexChanged
End If
End If
End Sub
Private Sub gridComboBox_SelectedIndexChanged(sender As Object, e As EventArgs)
Dim dropDown As ComboBox = TryCast(sender, ComboBox)
if not(dropDown is nothing) then
Dim drv as DataRowView = dropDown.SelectedItem
if Not (drv is nothing) then
Debug.Print(drv("item"))
end if
end if
End Sub
The SelectedIndexChanged event is raised as per a ComboBox used outside of a DataGridView.
I have been tasked with creating a cinema booking system in VB.net by my teacher. So far I have created 50 CheckBoxes and I am trying to rename them all to seat (number). I have this code in my Form1.load but it is not working because it is a type and not an expression. I tried using a variable for this but it did not work.
Here is my code:
For count As Integer = 1 To 54 Step 1
CheckBox(count).text = "Seat " & count
Next
Please help, and or recommend me another way to accomplish this.
set the name of the checkbox when you create it. To find out how to create a checkbox programmatically add a checkbox to a form then look at .designer.vb
dim cb as new checkbox
cb.name = "1"
cb.text = "Seat 1"
you need to also add the location and other properties
If you have already created your textboxes with names like 1, 2 then iterate through and get the numbers like this: If you call them CB_1 then cut the CB_ off before looking for the number.
dim cbNumber as int16
For Each c As Control In myContainer.Controls
If c.GetType() Is GetType(CheckBox) Then
cbnumber = cint(c.name)
c.text = "Seat" & cbnumber
End If
Next
Well, here's my approach. In order to test just drop on a FlowLayoutPanel, a Button, and a NumericUpDownonto the form.
Option Strict On
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For count As Integer = 1 To 54 Step 1
' Make a new CheckBox
Dim chkBox As New CheckBox()
' Setup the Checkbox
With chkBox
.Tag = count.ToString
.Name = CStr("seatCheckBox" & count.ToString)
.Text = String.Format("Seat {0}", count)
.ThreeState = False
.Checked = False
End With
' add an event listener for the checkbox checkstate changed event
AddHandler chkBox.CheckStateChanged, AddressOf Me.CheckBox_CheckStateChanged
' Add the checkbox to the control
Me.FlowLayoutPanel1.Controls.Add(chkBox)
' Keep the user from picking something that doesn't exist
Me.NumericUpDown1.Maximum = CDec(count)
Next
' Add and event listener for the find button click event
AddHandler Button1.Click, AddressOf Me.FindButton_Clicked
End Sub
' Find the checkbox in the form and return it
Private Function GetCheckBox(ByVal seatNumber As Integer) As CheckBox
Dim chkbox As CheckBox
' Try to find the Checkbox
Try
chkbox = TryCast(Me.Controls.Find(CStr("seatCheckBox" & seatNumber.ToString), True).First, CheckBox)
Catch ex As Exception
chkbox = Nothing
End Try
'Check if the trycast worked
If IsNothing(chkbox) Then
Throw New ArgumentOutOfRangeException("seatNumber", "The seat number to be searched for was not found")
Else
Return chkbox
End If
End Function
' Handle the Chekbox checkState event.
Private Sub CheckBox_CheckStateChanged(sender As Object, e As EventArgs)
' Convert to Checkbox
Dim chkBox As CheckBox = DirectCast(sender, CheckBox)
' Simple result string
Dim resultstring As String = CStr("Seat Number {0} is now {1}.")
' Set the values
Select Case chkBox.Checked
Case True
resultstring = String.Format(resultstring, chkBox.Tag, "taken")
Case False
resultstring = String.Format(resultstring, chkBox.Tag, "available")
End Select
' Display it
MsgBox(resultstring)
End Sub
Private Sub FindButton_Clicked(sender As Object, e As EventArgs)
Try
' Get the checkbox and return it's name
MsgBox(GetCheckBox(CInt(Me.NumericUpDown1.Value)).Name.ToString)
Catch ex As Exception
' Display the error
MsgBox(ex.Message)
End Try
End Sub
End Class
I have a datagridview which has a combox column that contains two values. When a row's combobox value has been changed I'm updating the backend database with the change.
The core problem is the data only changes after you click on the drop down arrow, and select the record. If you click on the combobox cell itself and select the value it doesn't do anything because the combobox selected item is empty.
What's confusing me is this works correctly within Visual Studio apart from the initial click following this it works fine, but when the application is ran directly the combobox runs slow, it takes 2 to 4 clicks of the combo box to actually detect that the value has changed.
This is the editcontrol handler.
Private Sub DataGridView_Changer(sender As Object, e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) _
Handles DataGridView.EditingControlShowing
Try
Dim Combo As ComboBox = CType(e.Control, ComboBox)
If Not IsNothing(Combo.SelectedItem) Then
RemoveHandler Combo.SelectedIndexChanged, New EventHandler(AddressOf ComboHandler)
AddHandler Combo.SelectedIndexChanged, New EventHandler(AddressOf ComboHandler)
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
This is the combobox handler where the data change occurs and updates the DB
Private Sub ComboHandler(sender As Object, e As EventArgs)
Try
Dim EmailID As Integer = DataGridView.CurrentRow.Cells("EmailID").Value
Dim Sent As Boolean = DataGridView.CurrentRow.Cells("BeenSent").Value
If Sent = True Then
Exit Sub
End If
Dim EMRec As DBClass.EmailRecordDB = EmailArchive.Where(Function(X) X.EmailID = EmailID).FirstOrDefault
Dim Combo As ComboBox = CType(sender, ComboBox)
If Combo.SelectedItem.ToString = "Failed" Then
EMRec.SentAttempt = 999
EMRec.BeenSent = False
ElseIf Combo.SelectedItem.ToString = "Resend" Then
EMRec.SentAttempt = 0
EMRec.BeenSent = False
End If
EMRec.ResetStatus() 'DB Update
DirtyCell()
Exit Sub
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Sub DirtyCell() 'Handles DataGridView.CurrentCellDirtyStateChanged
If DataGridView.IsCurrentCellDirty Then
Try
DataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit)
ContextualSearch() ' Refresh Grid
Catch ex As Exception
MsgBox(ex.Message)
End Try
End If
End Sub
UPDATE 24/04/2014
I've tweaked DirtyCell() and removed the if statement, so it commits the change regardless of if the cell is dirty or not. This seems to have made a bit of an improvement.
Sub DirtyCell() 'Handles DataGridView.CurrentCellDirtyStateChanged
Try
DataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit)
ContextualSearch() ' Refresh Grid
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
UPDATE 25/04/2014
I've still got an issue with the combobox cell being initially selected. It still requires 3+ clicks for the value change to actually take effect and trigger the combohandler event.
I am at a loss as to how to resolve this.
ok here is what i figured. the selectedIndexChanged does not work properly in many cases like yours, and mine sometimes. i prefer SelectionChangeCommited. Another issue is with your AddHandler and removeHandler. You should Store your selected combo in a global varable and then remove event handler when your start editing the next combo. see the suggested code below. it is working here for me :)
Edit like below in DataGridView_Changer:
Private lastCombo As ComboBox ''global variable to remember last combo with eventHandler i
Private Sub DataGridView_Changer(sender As Object, e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) _
Handles DataGridView.EditingControlShowing
Try
Dim Combo As ComboBox = CType(e.Control, ComboBox)
If Not IsNothing(Combo.SelectedItem) Then
If Not IsNothing(lastCombo) Then
RemoveHandler lastCombo.SelectionChangeCommitted, New EventHandler(AddressOf ComboHandler)
End If
lastCombo = Combo
AddHandler lastCombo.SelectionChangeCommitted, New EventHandler(AddressOf ComboHandler)
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
good luck!!!
Instead of trapping and attempting to do an update while the edit event was occurring (hindsight)
I used the CellValueChanged event.
The Combobox field contains 2 values but by default the value of the cell was empty.
When CellValueChanged is triggered it's after the cell's value has been updated.
I'd added CurrentCellDirtyStateChanged to DirtyCell to automatically commit the data change and rerun the query.
Such a simple change as using CellvalueChanged fixed the issue.
I have a DataGridView (called DataGridViewSecurity) in VB.net (Visual Studio 2010) which is bound to a DataTable (called DataTableSecurity) in a DataSet (called DataSetSecurity). I have added a nonbound column (called nSecurityComboBox) that I set based on an integer field (called nSecLevel) in the DataTable. After setting the combobox, it doesn't display anything in the combobox, but when you select the combobox, the 5 values in it's items collection show.
Here's the code I'm using to add a record to the DataTable and then to set the combobox:
Sub Foo()
.
.
.
DataSetSecurity.Tables(0).Rows.Add(New Object() {sName, sID, sSec})
ComboCell_Select(nRow, 3, DataGridViewSecurity, sSecRecs.nSecLevel)
MessageBox.Show("Value for the combo set at " + DataGridViewSecurity.Rows(nRow).Cells(3).Value.ToString)
.
.
.
End Sub
Private Sub ComboCell_Select(ByVal dgvRow As Integer, _
ByVal dgvCol As Integer, _
ByRef DGV As DataGridView,
ByRef nComboBoxRow As Int16)
Try
Dim CBox As DataGridViewComboBoxCell = CType(DGV.Rows(dgvRow).Cells(dgvCol), DataGridViewComboBoxCell)
Dim CCol As DataGridViewComboBoxColumn = CType(DGV.Columns(dgvCol), DataGridViewComboBoxColumn)
CBox.Value = CCol.Items(nComboBoxRow)
DGV.UpdateCellValue(dgvCol, dgvRow)
'MessageBox.Show("New value in the combo box = " + CBox.Value.ToString)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
The messagebox.show in Foo shows the correct value for the combobox, but nothing is displayed.
Anyone see what I'm doing wrong?
Thanks.
-NCGrimbo
In the end, I found some C# code that I converted to VB.net to fix the issue. Here's the code:
Private Sub DataGridViewSecurity_EditingControlShowing(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridViewSecurity.EditingControlShowing
Dim cellComboBox As ComboBox = TryCast(e.Control, ComboBox)
If cellComboBox IsNot Nothing Then
' make sure the handler doen't get registered twice
RemoveHandler cellComboBox.SelectionChangeCommitted, AddressOf Me.CellComboBoxOnSelectionChangeCommitted
AddHandler cellComboBox.SelectionChangeCommitted, AddressOf Me.CellComboBoxOnSelectionChangeCommitted
End If
End Sub
Private Sub CellComboBoxOnSelectionChangeCommitted(ByVal sender As Object, ByVal e As EventArgs)
Dim comboBox As DataGridViewComboBoxEditingControl = TryCast(sender, DataGridViewComboBoxEditingControl)
If sender Is Nothing Then
Return
End If
If comboBox.SelectedItem Is Nothing Then
Return
End If
If Me.DataGridViewSecurity.CurrentCell.Value = comboBox.SelectedItem Then
Return
End If
Me.DataGridViewSecurity.CurrentCell.Value = comboBox.SelectedItem
End Sub
If I understand the question right, all values are in the combobox just not being selected by default properly? I think I just had this problem a few days ago, here's what I have now.
'Create the combobox column
Dim comboBox As New DataGridViewComboBoxColumn()
'Add some stuff to the combobox
comboBox.Items.Add("FirstItem")
comboBox.Items.Add("SecondItem")
'Select the first item
comboBox.DefaultCellStyle.NullValue = comboBox.Items(0)
'Now add the whole combobox to the DataGridView
dgvItems.Columns.Add(comboBox)
Hope this helps!
Using VB.Net, I have a DataGridView with a ComboBox Column. What even do I use for when the user changes a selection in the ComboBox?
you can this event when the combobox value has been selected ...
Private Sub dataGridView_EditingControlShowing(ByVal sender As Object, ByVal e As DataGridViewEditingControlShowingEventArgs)
Try
If (Me.dataGridView.CurrentCell.ColumnIndex = CType(Column.Col,Integer)) Then
Dim comboBox As ComboBox = CType(e.Control,ComboBox)
If (Not (comboBox) Is Nothing) Then
AddHandler comboBox.SelectedIndexChanged, AddressOf Me.ComboBoxIndexChanged
End If
End If
Return
Catch Ex As Exception
Utils.ErrMsg(Ex.Message)
Return
End Try
End Sub
SelectedValueChanged
.FormatedValue as in Grid.Item.FormatedValue instead of Value
CurrentCellDirtyStateChanged - then test for the current cell being in your column of concern.