VB.NET Concurrency Exception with DataGridView - vb.net

I have encountered a with my datagridview, I bound it to a datatable and am calling and the handler on row is as follows
Dim cmdBuild As New SqlCommandBuilder(sda)
sda.Update(dgv.DataSource)
sda is SqlDataAdapter
so the problem is it works fine, any changes are updated to the database, but the concurrency exception pops up and I understand it is due to updating a ghost row in the database, now what I don't know is how do I go about it, how do I prevent it from happening. spent a lot of time on this one thing so any help that will sort me out will be HIGHLY appreciated. Thanks in advance.
P.S. If more code is needed I'll post it.
Edit
Public Sub editUsers(ByRef mainPanel As CustomTabControl, ByRef dt As System.Data.DataTable)
For i As Integer = 0 To mainPanel.TabCount - 1
If mainPanel.TabPages(i).Text = "Excel users" Then
mainPanel.SelectedTab = mainPanel.TabPages(i)
Exit Sub
End If
Next
Dim tb As New TabPage("Excel users")
Dim datagrid As New DataGridView
datagrid.AllowUserToAddRows = False
dt.Rows.Add(dt.NewRow)
datagrid.DataSource = dt
AddHandler datagrid.RowLeave, AddressOf Home.dataUpdate
tb.Controls.Add(datagrid)
datagrid.Dock = DockStyle.Fill
mainPanel.TabPages.Add(tb)
mainPanel.SelectedTab = tb
datagrid.Columns("ID").Visible = False
datagrid.Columns("Username").AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
datagrid.Columns("Username").FillWeight = 45
datagrid.Columns("Password").AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
datagrid.Columns("Password").FillWeight = 45
End Sub
Public Sub dataUpdate()
Dim dgv As DataGridView = Nothing
For i As Integer = 0 To mainPanel.TabCount - 1
If mainPanel.TabPages(i).Text = "Excel users" Then
dgv = mainPanel.TabPages(i).Controls(0)
End If
Next
If IsNothing(dgv) Then
Exit Sub
End If
For i As Integer = dgv.DataSource.Rows.Count - 1 To 0 Step -1
If dgv.DataSource.Rows(i).RowState = DataRowState.Deleted Then
Continue For
End If
If IsDBNull(dgv.DataSource.Rows(i).Item(1)) Or IsDBNull(dgv.DataSource.Rows(i).Item(2)) Then
Exit Sub
End If
Next
Dim cmdBuild As New SqlCommandBuilder(sda)
sda.Update(dgv.DataSource)
dgv.DataSource.Rows.Add(dtt.NewRow)
End Sub
The code above is all the code that is involved with datagridview control

Related

What is the best way to loop this program?

This is one of the form, all the usercontrol value in this form will store in My.Settings
I have another form with a FlowLayoutPanel, everytime when the application start,
if Active checked then it will add a Button with discount value to the FlowLayoutPanel.
Should I add those usercontrol to a list and then loop through the list? Or what is the best way to solve this kind of problem?
UPDATED
How can I add multiple item to list in 1 code? I getting this error when system run to line 5
An exception of type 'System.NullReferenceException' occurred in XXX.exe but was not handled in user code
Additional information: Object reference not set to an instance of an object.
Public Sub RefreshDiscount(ByRef ref As scr_mainDiscount)
Dim li_disName As New List(Of TextBox)
Dim li_disValue As New List(Of TextBox)
Dim li_disType As New List(Of ComboBox)
Dim li_active As New List(Of CheckBox)
Dim tb_disName As TextBox() = {ref.tb_name1, ref.tb_name2, ref.tb_name3, ref.tb_name4, ref.tb_name5, ref.tb_name6, ref.tb_name7, ref.tb_name8, ref.tb_name9, ref.tb_name10}
Dim tb_disValue As TextBox() = {ref.tb_value1, ref.tb_value2, ref.tb_value3, ref.tb_value4, ref.tb_value5, ref.tb_value6, ref.tb_value7, ref.tb_value8, ref.tb_value9, ref.tb_value10}
Dim cb_disType As ComboBox() = {ref.cb_type1, ref.cb_type2, ref.cb_type3, ref.cb_type4, ref.cb_type5, ref.cb_type6, ref.cb_type7, ref.cb_type8, ref.cb_type9, ref.cb_type10}
Dim chkb_active As CheckBox() = {ref.CheckBox1, ref.CheckBox2, ref.CheckBox3, ref.CheckBox4, ref.CheckBox5, ref.CheckBox6, ref.CheckBox7, ref.CheckBox8, ref.CheckBox9, ref.CheckBox10}
li_disName.AddRange(tb_disName)
li_disValue.AddRange(tb_disValue)
li_disType.AddRange(cb_disType)
li_active.AddRange(chkb_active)
For index As Integer = 0 To li_active.Count - 1
If li_active(index).Checked = False Then
li_disName.RemoveAt(index)
li_disValue.RemoveAt(index)
li_disType.RemoveAt(index)
li_active.RemoveAt(index)
Else
Dim btn As New ctrl_DiscountButton
With btn
.Text = li_disName(index).Text
.Price = li_disValue(index).Text
.Type = li_disType(index).Text
End With
scr_sales.flp_discount.Controls.Add(btn)
End If
Next
li_disName.Clear()
li_disValue.Clear()
li_disType.Clear()
li_active.Clear()
End Sub
Here's a simple example showing how to find CheckBox1 thru CheckBox10, "by name", using the "searchAllChildren" option of Controls.Find():
For i As Integer = 1 To 10
Dim ctlName As String = "CheckBox" & i
Dim matches() As Control = Me.Controls.Find(ctlName, True)
If matches.Length > 0 AndAlso TypeOf matches(0) Is CheckBox Then
Dim cb As CheckBox = DirectCast(matches(0), CheckBox)
' do something with "cb"
If cb.Checked Then
' ... code ...
' possibly use code just like this to find the matching discount value control?
End If
End If
Next

Clearing Panel Jumps to Value Change Event of DatePicker and Never ends the loop

Here I am using Panel with some dynamic datetime editors on windows forms with VB.net. Before loading the panel i am trying to clear the panel. But this cause value changed event to run continuously and will never stop
When the date is entered in dynamically created datetime editor, value changed event is continuously running and will never stop.
How can I fix this
My code is as Below
Private Function LoadFlow()
Me.UltraPanel1.ClientArea.Controls.Clear()
Dim i As Integer = 0
'Check if datatable has rows and is not null
If dtFlowPanel.Rows.Count > 0 AndAlso dtFlowPanel IsNot Nothing Then
Do While (i < dtFlowPanel.Rows.Count)
'DatePicker
dtpicker = New UltraDateTimeEditor
dtpicker.Name = "Date" + i.ToString()
dtpicker.MaskInput = "{date} hh:mm"
dtpicker.MaskDisplayMode = MaskMode.IncludeBoth
dtpicker.SpinButtonDisplayStyle = Infragistics.Win.ButtonDisplayStyle.Always
dtpicker.Height = 20
dtpicker.Width = 140
'horizontal
dtpicker.Location = New Point((i * 140), 100)
AddHandler dtpicker.ValueChanged, AddressOf dtpicker_ValueChanged
If Not IsDBNull(dtFlowPanel.Rows(i)("CheckPointTimeValue")) Then
dtpicker.Value = dtFlowPanel.Rows(i)("CheckPointTimeValue")
Else
dtpicker.Value = Nothing
End If
Me.UltraPanel1.ClientArea.Controls.Add(dtpicker)
i = (i + 1)
Loop
End If
Return Nothing
End Function
My value changed event
Private Sub dtpicker_ValueChanged(sender As Object, e As EventArgs)
If Not DBNull.Value.Equals(chkdtFlowPanel.Rows.Item(0).Item("ConveyanceID")) AndAlso Not DBNull.Value.Equals(chkdtFlowPanel.Rows.Item(0).Item("TripID")) Then
ScreenProperty.ARG_ConveyanceID = chkdtFlowPanel.Rows.Item(0).Item("ConveyanceID")
ScreenProperty.ARG_TripID = chkdtFlowPanel.Rows.Item(0).Item("TripID")
Dim prevDatevalue As Object = Nothing
For Each o As Object In UltraPanel1.ClientArea.Controls
If TypeOf (o) Is UltraDateTimeEditor Then
Dim datePicker As UltraDateTimeEditor = o
If datePicker.Value <> Nothing Then
If prevDatevalue <> Nothing Then
If datePicker.Value < prevDatevalue Then
' Do something Previous value is Lesser
'lblSuccess.Text = "Please verify date entered."
'lblSuccess.ForeColor = Color.Red
Exit Sub
End If
End If
ScreenProperty.ARG_CheckPointTimeID = Convert.ToInt32(datePicker.Tag.Split(","c)(0))
ScreenProperty.ARG_TerminalCheckPointID = Convert.ToInt32(datePicker.Tag.Split(","c)(1))
ScreenProperty.ARG_CheckPointTimeValue = datePicker.Value
Helper.InsertCheckPointTimes(CType(ScreenProperty, KMCommonUITemplates.CUTScreenProperty), Me)
prevDatevalue = datePicker.Value
'ClearText()
End If
'lblSuccess.Text = "Data Saved Successfully."
'lblSuccess.ForeColor = Color.Green
End If
Next
'Else
' lblSuccess.Text = "Selected Order does not have Trip/Conveyance created."
' lblSuccess.ForeColor = Color.Red
Helper.GetCheckPointFlowByTerminalID(CType(ScreenProperty, KMCommonUITemplates.CUTScreenProperty), Me)
LoadFlow()
End If
End Sub
Since the event handler code is calling LoadFlow that in turn appears to trigger the eventhandler, you are entering an infinite loop.
Before the statement Me.UltraPanel1.ClientArea.Controls.Clear() in LoadFlow remove any eventhandlers. Something like this:
For Each c As Control In UltraPanel1.ClientArea.Controls
Dim dtp As UltraDateTimeEditor
dtp = TryCast(c, UltraDateTimeEditor)
If dtp IsNot Nothing Then
RemoveHandler dtp.ValueChanged, AddressOf DateTimePicker_ValueChanged
End If
Next

How To Refresh GridlookupEdit datasource with another datasource

here I will explain what I want to ask.
before I explain what is my problem.
I created a program and I add 1 forms, in my form I add combobox and components of deexpress is GridLookupEdit.
the function of the combobox itself which displays options category.
while Gridlookup will display data from the database based on the category selected from Combobox.
At the time I chose the first category, namely 'Study Program' from the combobox, then the data is successfully performing in GridLookup.
But When I choose a category of the Other, which is the data based Category I choose the existing data in the database, but it can not show all GridLookup.
And Gridlookup only list items that previously emptied and menyisahkan Name column of the previous data.
for code that I use and I Attach screenshot on the following page:
Private Sub CBCariOpt_SelectedIndexChanged(sender As Object, e As EventArgs) Handles CBCariOpt.SelectedIndexChanged
With CBCariOpt
If .SelectedIndex = -1 Or .Text = "" Then Exit Sub
If .SelectedIndex = 0 Or .SelectedIndex = 1 Or .SelectedIndex = 4 Or .SelectedIndex = 5 Then
GLOptCari.Properties.DataSource = DBNull.Value
FilDataBantuGridLookup(.SelectedIndex, GLOptCari, DKritria, General.Constant.ConfigPath)
Else
GLOptCari.SendToBack()
With DKritria
.BringToFront()
.Text = ""
.Focus()
.Select()
End With
End If
End With
End Sub
Code For FillData into Data source Gridlookup
Private Sub FilDataBantuGridLookup(SelIndex As Integer, GL As GridLookUpEdit, dkritria As MetroTextBox, path As String)
With QD
If SelIndex = 0 Then .FillToGridLook(QProdi, GL, "PRODI", "KODE", path)
If SelIndex = 1 Then .FillToGridLook(QJursan, GL, "JURUSAN", "KODE", path)
If SelIndex = 4 Then .FillToGridLook(QThAnktan, GL, "THN_ANGKATAN", "THN_ANGKATAN", path)
If SelIndex = 5 Then .FillToGridLook(QThWisda, GL, "THN_WISUDA", "THN_WISUDA", path)
.Dispose()
GL.Properties.PopupFormSize = New Size With {.Width = GL.Width} 'GridLookUpEdit
GL.BringToFront()
dkritria.SendToBack()
End With
End Sub
Query To DataSource In GridLookupEdit :
Public Sub FillToGridLook(ByVal query As String, FilCtl As DevExpress.XtraEditors.GridLookUpEdit, SDis As String, SVal As String, ByVal path As String)
Using KN As New Koneksi.Koneksi
If KN.OpenFromFile(path) Then
Using da As New MySqlDataAdapter(query, KN.OKoneksi)
Dim dt As New DataTable
dt = New DataTable
dt.Rows.Clear()
dt.Columns.Clear()
da.Fill(dt)
If dt.Rows.Count > 0 Then
FilCtl.Refresh()
FilCtl.RefreshEditValue()
With FilCtl.Properties
.DataSource = Nothing
.DataSource = dt
.DisplayMember = SDis
.ValueMember = SVal
.ImmediatePopup = True
.View.OptionsView.ShowColumnHeaders = False
End With
FilCtl.Refresh()
End If
da.Dispose()
dt.Dispose()
End Using
End If
KN.Dispose()
End Using
End Sub
For Result :
Screen Shoot
therefore, I would like to ask,:
How to refresh the DataSource in gridlookup who initially had to accommodate the initial data prior to the new data?

Trouble with Timer_tick not stopping

I'm very new to programming and vb.net, trying to self teach more so as a hobby, as I have an idea for a program that I would find useful, but I am having trouble getting past this issue and I believe it is to do with the timer.
I have a form of size.(600,600) with one button of size.(450,150) that is set location(100,50) on the form. When clicked I want to move down it's own height, then add a new button in it's place. The code included below works as desired for the first two clicks, but on the third click the button keeps moving and the autoscroll bar extends. I initially thought it was the autoscroll function or the location property, but realised that as the button keeps moving, the timer hasn't stopped. I am aware that the code is probably very clunky in terms of achieving the outcome, and that there are a few lines/variables that are currently skipped over by the compiler (these are from older attempts to figure this out).
I have looked around and can't find the cause of my problem. Any help would be greatly appreciated. Apologies if the code block looks messy - first go.
Public Class frmOpenScreen
Dim intWButtons, intCreateButtonY, intCreateButtonX 'intTimerTick As Integer
Dim arrWNames() As String
Dim ctrlWButtons As Control
Dim blnAddingW As Boolean
Private Sub btnCreateW_Click(sender As System.Object, e As System.EventArgs) Handles btnCreateW.Click
'Creates new Button details including handler
Dim strWName, strWShort As String
Dim intCreateButtonY2 As Integer
Static intNumW As Integer
Dim B As New Button
strWName = InputBox("Please enter the name name of the button you are creating. Please ensure the spelling is correct.", "Create W")
If strWName = "" Then
MsgBox("Nothing Entered.")
Exit Sub
End If
strWShort = strWName.Replace(" ", "")
B.Text = strWName
B.Width = 400
B.Height = 150
B.Font = New System.Drawing.Font("Arial Narrow", 21.75)
B.AutoSizeMode = Windows.Forms.AutoSizeMode.GrowAndShrink
B.Anchor = AnchorStyles.Top
B.Margin = New Windows.Forms.Padding(0, 0, 0, 0)
'Updates Crucial Data (w name array, number of w buttons inc Create New)
If intNumW = 0 Then
ReDim arrWNames(0)
Else
intNumW = UBound(arrWNames) + 1
ReDim Preserve arrWNames(intNumW)
End If
arrWNames(intNumW) = strWShort
intNumW = intNumW + 1
intWButtons = WButtonCount(intWButtons) + 1
'updates form with new button and rearranges existing buttons
intCreateButtonY = btnCreateW.Location.Y
intCreateButtonX = btnCreateW.Location.X
‘intTimerTick = 0
tmrButtonMove.Enabled = True
‘Do While intTimerTick < 16
‘ 'blank to do nothing
‘Loop
'btnCreateW.Location = New Point(intCreateButtonX, intCreateButtonY + 150)
B.Location = New Point(intCreateButtonX, intCreateButtonY)
Me.Controls.Add(B)
B.Name = "btn" & strWShort
intCreateButtonY2 = btnCreateW.Location.Y
If intCreateButtonY2 > Me.Location.Y Then
Me.AutoScroll = False
Me.AutoScroll = True
Else
Me.AutoScroll = False
End If
'MsgBox(intCreateButtonY)
End Sub
Function WButtonCount(ByRef buttoncount As Integer) As Integer
buttoncount = intWButtons
If buttoncount = 0 Then
Return 1
End If
Return buttoncount
End Function
Public Sub tmrButtonMove_Tick(sender As System.Object, e As System.EventArgs) Handles tmrButtonMove.Tick
Dim intTimerTick As Integer
If intTimerTick > 14 Then
intTimerTick = 0
End If
If btnCreateW.Location.Y <= intCreateButtonY + 150 Then
btnCreateW.Top = btnCreateW.Top + 10
End If
intTimerTick += 1
If intTimerTick = 15 Then
tmrButtonMove.Enabled = False
End If
End Sub
End Class
So my current understanding is that the tick event handler should be increasing the timertick variable every time it fires, and that once it has hits 15 it should diable the timer and stop the button moving, but it is not doing so.
Thanks in advance.
IntTimerTick is initialized to 0 at the beginning of every Tick event. This won't happen if you declare it to be static:
Static Dim intTimerTick As Integer

DataGridView not Refreshing/Updating/Reloading Data. After Child form closes

This is a VB.NET, Winforms App. I have a datagridview on "Form1" that uses a databinding.datasource which is an Entity Framework table. I fill the datagridview with the below function on Form1:
Sub PM_UnitViewGrid()
Try
_form1.UnitsBindingSource.DataSource = db.units.Where(Function(f) f.propertyId = _form1.CurrentPropertyId).OrderBy(Function(F) F.unitNumber)
_form1.UnitDataGridView.DataSource = _form1.UnitsBindingSource.DataSource
Dim iCount As Integer = _form1.UnitDataGridView.RowCount
For x As Integer = 0 To iCount - 1
If Not IsNothing(_form1.UnitDataGridView.Rows(x).Cells(4).Value) Then
Dim tid As Integer = _form1.UnitDataGridView.Rows(x).Cells(4).Value
Dim _ten As tenant = db.tenants.Single(Function(f) f.Occupantid = tid)
_form1.UnitDataGridView.Rows(x).Cells(1).Value = _ten.first_name + ", " + _ten.last_name
Else
Dim btnColumn As DataGridViewButtonCell = CType(_form1.UnitDataGridView.Rows(x).Cells(1), DataGridViewButtonCell)
btnColumn.Style.BackColor = Color.Green
_form1.UnitDataGridView.Rows(x).Cells(1).Value = "VACANT"
End If
Next
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
Return
End Sub
This works great and also assigns the needed values to an unbound column. The problem is that the cells(1) is a button. Which when clicked takes the user to another form as a new dialog window. The function for which is below. However, once the changes are made in that form I need for the datagridview to refresh the data that its using from the database and show the correct data. As it stands right now the values are not updating on the datagridview unless the app is completely exited and restarted. Nothing I have found seems to work and Refresh and Update only redraw the control. I need the underlying datasource to refresh and then the datagridview once the child form is exited.. This has had me stumped for a good 36 hours now and I am lost as to why nothing I am trying is working. ANY and all help would be greatly appreciated.
The sub that loads the child form based on the cells(1) button clicked is as follows:
Private Sub UnitDataGridView_CellContentClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles UnitDataGridView.CellContentClick
UnitDataGridView.CommitEdit(DataGridViewDataErrorContexts.CurrentCellChange)
Dim y As DataGridViewCellEventArgs = e
Dim Tid As Integer = Nothing
If e.ColumnIndex = 1 Then
If Not e.RowIndex = -1 Then
If Not IsNothing(UnitDataGridView.Rows(e.RowIndex).Cells(4).Value) Then
currentTenent = UnitDataGridView.Rows(e.RowIndex).Cells(4).Value
TenentIdentification = currentTenent
If Not IsNothing(e) Then
If Not IsNothing(UnitDataGridView.Rows(e.RowIndex).Cells(4).Value) Then
Tid = UnitDataGridView.Rows(e.RowIndex).Cells(4).Value
Dim _ten As tenant = db.tenants.Single(Function(f) f.Occupantid = Tid) 'tenant is a table entity
TenantViewSubs.tenId = _ten.Occupantid
Dim t As New TenantView
t.tenId = tid
t.ShowDialog()
End If
End If
PropertyManagSubs.PM_UnitViewGrid() 'This is the function that is above that fills the datagridview
Else
Dim uTview As New UnassignedTenants
uTview.selectedProperty = selectedProperty 'selectedProperty is Integer
uTview.ShowDialog()
PropertyManagSubs.PM_UnitViewGrid() 'This is the function that is above that fills the datagridview
End If
End If
End If
End Sub
I tried each of the following code blocks after the t.ShowDialog() line with no change at all.
UnitDataGridView.Refresh()
.
UnitsBindingSource.Dispose()
UnitsBindingSource.DataSource = db.units.Where(Function(f) f.propertyId = selectedProperty).OrderBy(Function(f) f.unitNumber)
UnitDataGridView.DataSource = UnitsBindingSource.DataSource
.
UnitsBindingSource.DataSource = nothing
unitsBindingSource.DataSource = db.units.Where(Function(f) f.propertyId = selectedProperty).OrderBy(Function(f) f.unitNumber)
UnitDataGridView.DataSource = UnitsBindingSource.DataSource
I finally fixed this on my own.. It was in the way I passed my db context to the databinding..
I simply wrote the below sub:
Private Sub UpdateValues()
Dim context As New storageEntities 'storageEntities is an Entity
Dim query = context.units.Where(Function(F) F.propertyId = selectedProperty).OrderBy(Function(f) f.unitNumber)
UnitDataGridView.DataSource = query
End Sub
Then anytime a child form updated data I simply call
UpdateValues()
After the dialog box closes.
This may help someone else with the same problems so that is why I am posting it.