Combo box not refreshed after insert/delete records - vb.net

I am using vb.net and access 2007
I have a problem regarding combo box refresh
This is my code:
Private Sub comboRefresh()
Try
cmbSn_no.DataSource = Nothing
cmbSn_no.Items.Clear()
Dim asql As String = ("SELECT * FROM Vendor_det")
da = New OleDb.OleDbDataAdapter(asql, cnnOLEDB)
da.Fill(ds, "Vendor_det")
cmbSn_no.ValueMember = "sr_no"
cmbSn_no.DataSource = ds.Tables(0)
cmbSn_no.SelectedIndex = 0
'DataGridView1.DataSource = ds.Tables(0)
'DataGridView1.Update()
Catch ex As Exception
MsgBox("ERROR : " & ex.Message.ToString)
End Try
End Sub
Private Sub cmbSn_no_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmbSn_no.SelectedIndexChanged
Dim asql As String = ("SELECT * FROM Vendor_det where sr_no='" & cmbSn_no.Text & "'")
cnnOLEDB.Open()
cmd = New OleDb.OleDbCommand(asql, cnnOLEDB)
dr = cmd.ExecuteReader
If dr.Read = True Then
cmbSn_no.Text = dr("sr_no")
txtPart_no.Text = dr("part_no")
..........
End If
cnnOLEDB.Close()
End Sub
And i call comborefresh() method from add and delete record button click events.
if i dont use the commented code and click on add / delete button then the output comes some how like this:
records in db:
abcd123
bbbc123
if i add a record cccc123.. it should update and my combo box should fill with following records:
abcd123
bbbc123
cccc123
but it fills with
abcd123
bbbc123
cccc123
abcd123
bbbc123
and if i use the commented line then the combo box is filled with "System.Data.DataRowView"
No prompted error comes but i am not getting my answer...
even i have tried with....
combobox.refresh()
combobox.selectedindex=-1
and
combobox.items.clear()
it does not work
Please resolve my problem....
Thank you in advance...:)

Your code to refresh the ComboBox should be OK, but no need to call cmbSn_no.Items.Clear() since cmbSn_no.DataSource = Nothing will remove all data from the ComboBox.
However, based on your code I assume that you declare your DataSet (ds) as form variable, thus when you want to fill in the ds, the old data (first 2 data - abcd123 bbbc123) is still there, and then run the Fill method will add those old data with a whole set of new data - that are abcd123 bbbc123 cccc123. To make sure, try to add this code after da.Fill(ds, "Vendor_det"):
MsgBox.Show(ds.Tables(0).Rows.Count)
I think it will show 5, not 3. If that's the case, try to refresh the DataSet first before Fill, either by creating a new instance of DataSet, or delete the table.

Related

datagridview last programmatically changed cell does not get included in changedrows

VB.net app changes values in a datagridview programmatically. The values are all as they should be, but the save routine (dtShipments is the datatable that is the source for the datagridview)
Dim dtChanges As DataTable = dtShipments.getchanges()
If more than one has changed, dtChanges is always missing the last row.
In the routine that changes the cell values, I have tried DatagridView1.EndEdit and DatagridView1.CommitEdit, but the behavior is the same. I even tried adding a SendKeys.Send(vbTab) line, since hitting the tab key when making the changes manually is enough to get all the changes to show up in .GetChanges.
What am I missing?
code per request:
Private Sub btnAssign_Click(sender As Object, e As EventArgs) Handles btnAssign.Click
strModErr = "Form1_btnAssign_Click"
Dim sTruck As String = ""
Try
sTruck = Me.DataGridView2.SelectedCells(0).Value.ToString
For Each row As DataGridViewRow In DataGridView1.SelectedRows
row.Cells("Truck").Value = sTruck
Next
DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
Catch ex As Exception
WriteErrorToLog(Err.Number, strModErr + " - " + Err.Description)
End Try
End Sub
Private Function SaveChanges() As Boolean
strModErr = "Form1_SaveChanges"
Dim Conn As New SqlConnection(My.Settings.SQLConnectionString)
Dim sSQL As String = "UPDATE fs_Shipments SET Truck = #Truck, Stop = #Stop WHERE SalesOrder = #SO"
Dim cmd As New SqlCommand(sSQL, Conn)
Dim sSO, sTruck As String
Dim iStop As Integer = 0
Try
DataGridView1.EndEdit()
DataGridView1.ClearSelection()
Dim dtChanges As DataTable = dtShipments.getchanges() 'DataRowState.Modified
If Not dtChanges Is Nothing Then
Conn.Open()
For Each row As DataRow In dtChanges.Rows
sSO = row("SalesOrder").ToString
sTruck = row("Truck").ToString
iStop = CInt(row("Stop").ToString)
With cmd.Parameters
.Clear()
.AddWithValue("#SO", sSO)
.AddWithValue("#Truck", sTruck)
.AddWithValue("#Stop", iStop)
End With
cmd.ExecuteNonQuery()
Next
End If
Return True
Catch ex As Exception
WriteErrorToLog(Err.Number, strModErr + " - " + Err.Description)
Return False
End Try
End Function
I am not exactly 100% sure why this happens. The problem appears to be specific to when the user “selects” the cells in the first grid, and then calls the SaveChanges code “BEFORE” the user has made another selection in the first grid. In other words, if the user “selects” the rows to “assign” the truck to in grid 1, then, “AFTER” the “selected” cells have been filled with the selected truck, THEN, the user selects some other cell in grid 1, THEN calls the save changes code. In that case the code works as expected.
All my attempts at committing the changes, either failed or introduced other issues. I am confident a lot of this has to do with the grids SelectedRows collection. IMHO, this looks like a risky way to set the cell values, I would think a more user-friendly approach may be to add a check box on each row and assign the truck values to the rows that are checked. But this is an opinion.
Anyway, after multiple attempts, the solution I came up with only further demonstrates why using a BindingSource is useful in many ways. In this case, it appears the DataTable is not getting updated with the last cell change. Again, I am not sure “why” this is, however since it appears to work using a BindingSource, I can only assume it has something to do with the DataTable itself. In other words, before the “Save” code is executed, we could call the tables AcceptChanges method, but then we would lose those changes. So that is not an option.
To help, below is a full (no-fluff) example. In the future, I highly recommend you pull out the parts of the code that do NOT pertain to the question. Example, all the code that saves the changes to the DB is superfluous in relation to the question… so remove it. The more unnecessary code you add to your question only increases the number of SO users that will “ignore” the question. If you post minimal, complete and working code that reproduces the problem so that users can simply copy and paste without having to add addition code or remove unnecessary code will increase you chances of getting a good answer. Just a heads up for the future.
The solution below simply adds a BindingSource. The BindingSource’s DataSource is the DataTable dtShipments then the BindingSource is used a DataSource to DataGridView1. Then in the SaveChanges method, “before” the code calls the dtShipment.GetChanges() method, we will call the BindingSources.ResetBinding() method which should complete the edits to the underlying data source, in this case the DataTable dtShipments.
If you create a new VS-VB winforms solution, drop two (2) grids and two (2) buttons onto the form as shown below, then change the button names to “btnAssign” and “btnApplyChanges.” The assign button will add the selected truck in grid two to the selected rows in grid one. The apply changes button simply resets the binding source and displays a message box with the number of rows that were changed in the dtShipments DataTable. It should be noted, that the code calls the dtShipments.AcceptChanges() method to clear the changes. Otherwise, the code will update changes that have already been made.
Dim dtShipments As DataTable
Dim dtTrucks As DataTable
Dim shipBS As BindingSource
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
dtShipments = GetShipmentsDT()
shipBS = New BindingSource()
shipBS.DataSource = dtShipments
dtTrucks = GetTrucksDT()
dtShipments.AcceptChanges()
DataGridView1.DataSource = shipBS
DataGridView2.DataSource = dtTrucks
End Sub
Private Function GetShipmentsDT() As DataTable
Dim dt = New DataTable()
dt.Columns.Add("ID", GetType(String))
dt.Columns.Add("Truck", GetType(String))
dt.Rows.Add(1)
dt.Rows.Add(2)
dt.Rows.Add(3)
dt.Rows.Add(4)
Return dt
End Function
Private Function GetTrucksDT() As DataTable
Dim dt = New DataTable()
dt.Columns.Add("Truck", GetType(String))
For index = 1 To 10
dt.Rows.Add("Truck" + index.ToString())
Next
Return dt
End Function
Private Sub btnAssign_Click(sender As Object, e As EventArgs) Handles btnAssign.Click
Dim sTruck = DataGridView2.SelectedCells(0).Value.ToString
'Dim drv As DataRowView
For Each row As DataGridViewRow In DataGridView1.SelectedRows
'drv = row.DataBoundItem
'drv("Truck") = sTruck
row.Cells("Truck").Value = sTruck
Next
'DataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit)
'shipBS.ResetBindings(True)
'DataGridView1.CurrentCell = DataGridView1.Rows(0).Cells(0)
End Sub
Private Function SaveChanges() As Boolean
Try
shipBS.ResetBindings(True)
Dim dtChanges As DataTable = dtShipments.GetChanges()
If (dtChanges IsNot Nothing) Then
MessageBox.Show("There are " & dtChanges.Rows.Count & " rows changed in the data table")
' update sql DB
dtShipments.AcceptChanges()
End If
Return True
Catch ex As Exception
Return False
End Try
End Function
Private Sub btnApplyChanges_Click(sender As Object, e As EventArgs) Handles btnApplyChanges.Click
Dim ChangesMade As Boolean
ChangesMade = SaveChanges()
End Sub
Lastly, since you are using VB… I highly recommend that you set the “Strict” option to “ON.” When this option is ON, it will flag possible errors that you may be missing. To do this for all future VB solutions, open VS, close any solutions that may be open, then go to Tools->Options->Projects and Solutions->VB Defaults, then set “Option Strict” to “On.” The default setting is off.
I hope this makes sense and helps.

Commands on Form Load

I have a command in a form which activates on Form Load which is as follows
Private Sub frm_15_IssueWarning_Load(sender As Object, e As EventArgs) Handles MyBase.Load
lbl_incidentid.Text = frm_6_UpdateIncident.lbl_incidentid.Text
'checks to see if a containment already exists for the Incident, if it does, hide the save containment button
Dim SqlString As String = "select [containmentid],[incidentid],[containmentdate],[containment] from [containment] WHERE [incidentid] = #incidentid"
Using conn As New OleDbConnection(ConnString)
Using command As New OleDbCommand(SqlString, conn)
command.Parameters.AddWithValue("#incidentid", lbl_incidentid.Text)
Using adapter As New OleDbDataAdapter(command)
conn.Open()
Dim reader As OleDbDataReader = command.ExecuteReader()
Try
If reader.Read() Then
Button1.Visible = False
Else
Button1.Visible = True
End If
Finally
reader.Close()
End Try
End Using
End Using
End Using
And all this works great, however the first command
lbl_incidentid.Text = frm_6_UpdateIncident.lbl_incidentid.Text
If I remove this line and place it in form 6 so that when pressing the button on form 6 to open form 15 it includes the line
lbl_incidentid.Text = frm_15_IssueWarning.lbl_incidentid.Text
The rest of the command on form load no longer works, previously this has'nt been a problem because you could only access form 15 from one location but now this is changing so the form can be opened from various locations. Is there a command I can write here so that the form knows what form was open/pressed in order to make it here and act accordingly or can anyone suggest another way round this issue? I apologise if this doesnt make much sense, its a bit of a ramble.
In the end I changed the forms a little, instead of opening the form and closing the previous form straight away I inserted an if statement to see what previous form was open before closing it so the new form could act accordingly, please see example below
'checks to see which form is open to see where to get incident if from
If frm_6_UpdateIncident.Visible = True Then
Me.lbl_incidentid.Text = frm_6_UpdateIncident.lbl_incidentid.Text
frm_6_UpdateIncident.close()
End If
If frm_17_IncidentView.Visible = True Then
Me.lbl_incidentid.Text = frm_17_IncidentView.lbl_incidentid.Text
frm_17_IncidentView.close()
End If
It was actually really simple, no idea why I didint think of this in the first place

How to make sortable a DataGrid bounded with a table

I load data on a DataGrid from a SQLite database with code like this:
conn.Open()
Dim sql = "SELECT * FROM TableDataGrid"
Dim cmdConnection As SQLiteCommand = New SQLiteCommand(sql, conn)
Dim da As New SQLiteDataAdapter
da.SelectCommand = cmdConnection
Dim dt As New DataTable
da.Fill(dt)
MyDataGrid.DataSource = dt
When the user click on a Row I display the data on a few textbox, combobox, no problem at all.
Now I need to let the user sort the DataGrid by clicking the column he want and of course is not that simple.
After research on the "e.RowIndex >= 0" and "System.NullReferenceException" error I understand that "The problem is that out of the box the BindingList does not support sorting! I know - sounds dumb but that is how it is." posted here: WinForms: DataGridView - programmatic sorting
So If I'm right I need to implement my own SortableBindingList but I'm confused because the samples of code are about a LIST and I load the database records on a TABLE (dt)
Example:
http://timvw.be/2007/02/22/presenting-the-sortablebindinglistt/
Another post say I can fix the trouble with a line like:
SortableBindingList<YourListType> sortableBindingList = new SortableBindingList<YourListType>(list)
What is the generic solution to make the DataGrid sortable on this case?
Thanks to the tips of the users I found the solution
Private Sub MyDataGrid_SelectionChanged(sender As Object, e As EventArgs) Handles MyDataGrid.SelectionChanged
'Check if the user clicked on a header or a row
Try
If MyDataGrid.CurrentRow.Index = Nothing Then
'Header clicked!!
Else
'Row clicked!!!
'Here I load the data of the clicked row on my form
FormCleanDataEntry()
FormShowRowData()
End If
Catch ex As Exception
'MsgBox(ex.ToString())
End Try
End Sub
The curiosity is that the exception is thrown but anyway I don't show any message to the user and the DataGrid is sorted and the program works fine

Updating Image on database MSAccess Database Vb.net?

I want to update images in the database but when i press the button it won't update , I don't have any errors on my code. I added some code in "com.executequery" block to try if i get errors, and i get messagebox result "Error"
Private Sub updatebtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles updatebtn.Click
If Agetxt.SelectedItem = Nothing Or gendertxt.SelectedItem = Nothing Or Yrlvltxt.SelectedItem = Nothing Or PictureBox1.Image Is Nothing Then
MsgBox("Please do not leave required fields blanks.", vbExclamation, "Warning!")
Else
Dim memstream As New MemoryStream
Dim datapic_update As Byte()
Me.PictureBox1.Image.Save(memstream, Imaging.ImageFormat.Jpeg)
datapic_update = memstream.GetBuffer()
memstream.Read(datapic_update, 0, memstream.Length)
'to check if connection is open
If con.State = ConnectionState.Open Then
con.Close()
End If
'Updating DB
Dim editQ As String = "Update Infos SET FirstName=#f1, SurName=#f2, MiddleName=#f3, [Birthdate]=#f4, Gender=#f5, HomeAddress=#f6, CityAddress=#f7, BaranggayAddress=#f8, EmailAdd1=#f9, Birthplace=#f10, Yearlevel=#f11, Course=#f12, Emailadd2=#f13, [Age]=#f14, [Telnum]=#f15, [Mobilenum1]=#f16, [Mobilenum2]=#f17, FathersName=#f18, FathersL=#f19, MothersName=#f20, MothersL=#f21, FathersOcc=#f22, MothersOcc=#f23, StreetAdd=#f24, [Image]=#Image WHERE [StudentID]=#fid "
Dim com As New OleDbCommand(editQ, con)
con.Open()
com.Parameters.AddWithValue("#fid", Stdntid.Text.ToString)
com.Parameters.AddWithValue("#f1", fname.Text)
com.Parameters.AddWithValue("#f2", Sname.Text)
com.Parameters.AddWithValue("#f3", Mname.Text)
com.Parameters.AddWithValue("#f4", Datetxt.Value.ToShortDateString)
com.Parameters.AddWithValue("#f5", gendertxt.SelectedItem.ToString)
com.Parameters.AddWithValue("#f6", homaddtxt.Text)
com.Parameters.AddWithValue("#f7", Cityadd.Text)
com.Parameters.AddWithValue("#f8", brgyadd.Text)
com.Parameters.AddWithValue("#f9", emailaddtxt.Text)
com.Parameters.AddWithValue("#f10", birthPtxt.Text)
com.Parameters.AddWithValue("#f11", Yrlvltxt.SelectedItem.ToString)
com.Parameters.AddWithValue("#f12", coursetxt.Text)
com.Parameters.AddWithValue("#f13", emailadd2txt.Text)
com.Parameters.AddWithValue("#f14", Agetxt.SelectedItem.ToString)
com.Parameters.AddWithValue("#f15", telnumtxt.Text)
com.Parameters.AddWithValue("#f16", mobilenum1txt.Text)
com.Parameters.AddWithValue("#f17", mobilenum2txt.Text)
com.Parameters.AddWithValue("#f18", FathersL.Text)
com.Parameters.AddWithValue("#f19", fatherstxt.Text)
com.Parameters.AddWithValue("#f20", MothersL.Text)
com.Parameters.AddWithValue("#f21", motherstxt.Text)
com.Parameters.AddWithValue("#f22", fOcc.Text)
com.Parameters.AddWithValue("#f23", mOcc.Text)
com.Parameters.AddWithValue("#f24", streetadd.Text)
' image content
Dim image As OleDbParameter = New OleDbParameter("#Image", SqlDbType.Image)
image.Value = datapic_update
com.Parameters.Add(Image)
com.ExecuteNonQuery()
If com.ExecuteNonQuery > 0 Then
MsgBox("Records Successfully Updated.", vbInformation, "Updated.")
Else
MsgBox("error")
End If
End If
con.Close()
End Sub
The fact that the ExecuteNonQuery call succeeds but returns zero means that there were no records in your database that match your WHERE clause. The reason is that you're adding your parameters incorrectly.
Both the Jet and ACE OLE DB providers use positional parameters only. Even though you can give your parameters names, those names are ignored by the provider. That means that you need to add your parameters to your OleDbCommand in the same order as they appear in the SQL code. You are not.
In your SQL code, #fid is the last parameter but this is the last parameter you add to the command:
com.Parameters.AddWithValue("#f24", streetadd.Text)
That is therefore the value being used to find matching records. Rearrange the code that adds parameters to the command and add #fid last and you'll be good to go.

Datagridview coloring cell

I'm experiencing a problem with the datagridview. I'm trying to create a program that allows me to run certain tests. I want to list them in a datagridview. Then with a counter I want the program to go through the active serverprocesses and run them. In the overview I want to visualize whether a process is active by coloring a cell that i add. I've done this before and used the same code but this time it doesn't seem to work. You can find my code for the load event of the form here. Can anyone tell me what I'm doing wrong?
Private Sub frmServerProcesses_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim strSQL As String
Dim oDR As SqlClient.SqlDataReader = Nothing
'bij het opstarten moet de stopknop disabled zijn
btnServerStop.Enabled = False
btnServerStart.Enabled = True
statServerProcesseslbl.Text = "Server ready"
'opvragen van de processen
strSQL = " SELECT * FROM SERVERPROCESSES"
Dim connection As New SqlConnection(SQLConnectstring)
Dim dataadapter As New SqlDataAdapter(strSQL, connection)
Dim ds As New DataSet()
connection.Open()
dataadapter.Fill(ds, "SERVERPROCESSES")
connection.Close()
dgvServerProcesses.DataSource = ds
dgvServerProcesses.DataMember = "SERVERPROCESSES"
dgvServerProcesses.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells
dgvServerProcesses.Columns("LASTRUNDATE").AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
'lege row die normaal wordt toegevoegd verwijderen
dgvServerProcesses.AllowUserToAddRows = False
'extra kolom toevoegen voor kleuren van actief of niet
dgvServerProcesses.Columns.Add("TEST", "TEST")
For i As Integer = 1 To dgvServerProcesses.Rows.Count - 1
If dgvServerProcesses.Rows(i).Cells(2).Value = "True" Then
dgvServerProcesses.Rows(i).Cells(2).Style.BackColor = Color.Black
End If
Next
'lege row die normaal wordt toegevoegd verwijderen
dgvServerProcesses.AllowUserToAddRows = False
End Sub
I've just tried to put both things in separate subs. So filling up the grid and marking the active ones are separate now. Both subs are called by the load sub. But still the colors don't work. But if I call the checkprocess with a button it does work. But what is also very strange is that the columncount is different. If I call it with a button he starts counting on 1 in the other case on 0. Can someone explain that to me? My new code to check the active boolean is shown here
Public Sub CheckProcessActive()
For i As Integer = 0 To dgvServerProcesses.Rows.Count - 1
If dgvServerProcesses.Rows(i).Cells(2).Value = "True" Then
dgvServerProcesses.Rows(i).Cells("ACTIVE").Style.BackColor = Color.Green
Else
dgvServerProcesses.Rows(i).Cells("ACTIVE").Style.BackColor = Color.Red
End If
Next
End Sub
The behavior you have noticed is normal. Even if you set the DataSource property, the DatagridView won't create columns and be populated until the grid is displayed, it's not populated immediately after setting this property.
You can use the DataGridView.DataBindingComplete event to be sure the grid is populated when you change the style and call CheckProcessActive() here.