How to save changes from DataGridView to the database? - vb.net

I would like to save the changes made to a DataGridView into the database MS SQL CE,
but i can't, the changes are not saved to the database....
This the code (VB.net):
Private Sub Form1_Load(ByVal sender As System.Object,
ByVal e As System.EventArgs) handles MyBase.Load
Dim con As SqlCeConnection = New SqlCeConnection(#"Data Source=C:\Users\utente\Documents\test.sdf")
Dim cmd As SqlCeCommand = New SqlCeCommand("SELECT * FROM mytable", con)
con.Open()
myDA = New SqlCeDataAdapter(cmd)
Dim builder As SqlCeCommandBuilder = New SqlCeCommandBuilder(myDA)
myDataSet = New DataSet()
myDA.Fill(myDataSet, "MyTable")
DataGridView1.DataSource = myDataSet.Tables("MyTable").DefaultView
con.Close()
con = Nothing
End Sub
Private Sub edit_rec()
Dim txt1, txt2 As String
Dim indice As Integer = DataGridView1.CurrentRow.Index
txt1 = DataGridView1(0, indice).Value.ToString '(0 is the first column of datagridview)
txt2 = DataGridView1(1, indice).Value.ToString '(1 is the second) MsgBox(txt1 + " " + txt2)
'
DataGridView1(0, indice).Value = "Pippo"
DataGridView1(1, indice).Value = "Pluto"
'
Me.Validate()
Me.myDA.Update(Me.myDataSet.Tables("MyTable"))
Me.myDataSet.AcceptChanges()
'
End Sub
Thank you for any suggestion.

You need to use myDA.Update, that will commit the changes. This is because any changes that you are making are made in the local instance of that dataset. And therefore disposed of just like any other variable.
... I can see that in your edit_rec sub, but what is calling that - there is nothing in the code that you have posted.

A little late perhaps.
In the Form load event, you open and close the connection.
And furthermore, all are local variables who loose any value or data when leaving the sub
Public Class Form1
Dim con As SqlCeConnection
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
con = New SqlCeConnection(#"Data Source=C:\Users\utente\Documents\test.sdf")
Dim cmd As SqlCeCommand = New SqlCeCommand("SELECT * FROM mytable", con)
con.Open()
myDA = New SqlCeDataAdapter(cmd)
Dim builder As SqlCeCommandBuilder = New SqlCeCommandBuilder(myDA)
myDataSet = New DataSet()
myDA.Fill(myDataSet, "MyTable")
DataGridView1.DataSource = myDataSet.Tables("MyTable").DefaultView
cmd.Dispose()
End Sub
***Put the closing of connection here instead or somewhere else suitable when you don't use it anymore***
Private Sub Form1_FormClosed(sender As Object, e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
con.Close()
con = Nothing
End Sub
Private Sub edit_rec()
Dim txt1, txt2 As String
Dim indice As Integer = DataGridView1.CurrentRow.Index
txt1 = DataGridView1(0, indice).Value.ToString '(0 is the first column of datagridview)
txt2 = DataGridView1(1, indice).Value.ToString '(1 is the second) MsgBox(txt1 + " " + txt2)
'
DataGridView1(0, indice).Value = "Pippo"
DataGridView1(1, indice).Value = "Pluto"
'You code to update goes here and not in my scope of answer
End Sub
End Class

I think you want to add # with your connection string
SqlConnection con;
con = New SqlConnection(#"Data Source=C:\Users\utente\Documents\test.sdf");

Related

Get Image from SQL using Listbox to picturebox VB

i'm trying to get the image from SQL to picturebox using Listbox in in VB.
here is my sql sample table.
and here is my VB Design form, so what I'm trying to do is when I load the form, if an item in the listbox is selected, i want it to get the image(Binary Data) from sql to picturebox in vb net.
and the code I'm working with it give me this error:
VB full code:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
connect()
Dim co As New SqlConnection("Data Source=WXCQSDQSD\SQLEXPRESS;Initial Catalog=food;Integrated Security = True")
co.Open()
Dim com As New SqlCommand("SELECT Image from Items where ItemName = '" & ListBox1.SelectedIndex & "'", co)
Dim img As Byte() = DirectCast(com.ExecuteScalar(), Byte())
Dim ms As MemoryStream = New MemoryStream(img)
Dim dt = GetDataFromSql()
Dim BndSrc As New BindingSource()
BndSrc.DataSource = dt
ListBox1.DisplayMember = "ItemName"
ListBox1.DataSource = BndSrc
TextBox1.DataBindings.Add("Text", BndSrc, "ItemID")
TextBox2.DataBindings.Add("Text", BndSrc, "ItemName")
TextBox3.DataBindings.Add("Text", BndSrc, "Details")
PictureBox1.Image = Image.FromStream(ms)
End Sub
Private Function GetDataFromSql() As DataTable
Dim dt As New DataTable
Using connection As New SqlConnection("Data Source=WXCQSDQSD\SQLEXPRESS;Initial Catalog=food;Integrated Security = True"),
cmd As New SqlCommand("select * FROM Items", connection)
connection.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
Return dt
End Function
Remove the picture retrieval from the Form.Load. We have selected all the data in the GetDataFromSql function. The magic happens in the ListBox1.SelectedIndexChanged method.
The SelectedIndexChanged will occur as a result of the code in the Form.Load and every time the selection changes. When we bind the the list box to to binding source the entire row is added as a DataRowView. We can use this to get the data in the Image column. First check if the field is null. Next cast to a byte array. Take the byte array and pass it to the constructor of a MemoryStream. Streams need to be disposed so it is in a Using block. Finally the stream can be assigned to the Image property of the PictureBox.
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim dt = GetDataFromSql()
Dim BndSrc As New BindingSource()
BndSrc.DataSource = dt
ListBox1.DisplayMember = "ItemName"
ListBox1.DataSource = BndSrc
TextBox1.DataBindings.Add("Text", BndSrc, "ItemID")
TextBox2.DataBindings.Add("Text", BndSrc, "ItemName")
TextBox3.DataBindings.Add("Text", BndSrc, "Details")
End Sub
Private Function GetDataFromSql() As DataTable
Dim dt As New DataTable
Using connection As New SqlConnection("Data Source=WXCQSDQSD\SQLEXPRESS;Initial Catalog=food;Integrated Security = True"),
cmd As New SqlCommand("select * FROM Items", connection)
connection.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
Return dt
End Function
Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedIndexChanged
Dim row = DirectCast(ListBox1.SelectedItem, DataRowView)
If row("Image") IsNot Nothing Then
Dim b() As Byte = DirectCast(row("Image"), Byte()) '< ------ Cast the field to a Byte array.
Using ms As New System.IO.MemoryStream(b)
PictureBox1.Image = System.Drawing.Image.FromStream(ms)
End Using
Else
PictureBox1.Image = Nothing
End If
End Sub
EDIT
I switched the code over to a database I have available for testing. Even though it is not your database, I am sure you will be able to follow the code.
Here is the schema of my database.
The main difference is I moved the DataTable to a class level variable so it can be seen from all methods. I changed the GetDataFromSql to a Sub. It adds the data to the class level DataTable (Bounddt). The AddItem method first gets the Byte() from a file. The row is added to the DataTable with an Object array with elements that match the DataTable.
Private Bounddt As New DataTable
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
GetDataFromSql()
Dim BndSrc As New BindingSource()
BndSrc.DataSource = Bounddt
ListBox1.DisplayMember = "CustomerID"
ListBox1.DataSource = BndSrc
TextBox1.DataBindings.Add("Text", BndSrc, "CustomerID")
TextBox2.DataBindings.Add("Text", BndSrc, "CustomerName")
End Sub
Private Sub GetDataFromSql()
Using connection As New SqlConnection("Data Source=****;Initial Catalog='Small Database';Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"),
cmd As New SqlCommand("select * FROM Sales.Customer", connection)
connection.Open()
Using reader = cmd.ExecuteReader
Bounddt.Load(reader)
End Using
End Using
'Return dt
End Sub
Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedIndexChanged
Dim row = DirectCast(ListBox1.SelectedItem, DataRowView)
If row("Picture") IsNot Nothing Then
Dim b() As Byte = DirectCast(row("Picture"), Byte()) '< ------ Cast the field to a Byte array.
Using ms As New System.IO.MemoryStream(b)
PictureBox1.Image = System.Drawing.Image.FromStream(ms)
End Using
Else
PictureBox1.Image = Nothing
End If
End Sub
Private Sub AddItem()
Dim picture = GetByteArr("C:\Users\maryo\OneDrive\Documents\Graphics\Animals\squirrel.png")
Bounddt.Rows.Add({5, "George", 74, 62, "George", picture})
End Sub
Private Function GetByteArr(path As String) As Byte()
Dim img = Image.FromFile(path)
Dim arr As Byte()
Dim imgFor As Imaging.ImageFormat
Dim extension = path.Substring(path.LastIndexOf(".") + 1)
'There is a longer list of formats available in ImageFormat
Select Case extension
Case "png"
imgFor = Imaging.ImageFormat.Png
Case "jpg", "jpeg"
imgFor = Imaging.ImageFormat.Jpeg
Case "bmp"
imgFor = Imaging.ImageFormat.Bmp
Case Else
MessageBox.Show("Not a valid image format")
Return Nothing
End Select
Using ms As New MemoryStream
img.Save(ms, imgFor)
arr = ms.ToArray
End Using
Return arr
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
AddItem()
End Sub
Imports System.Data.SqlClient
Imports System.IO
Public Class Form1
Dim con As SqlConnection
Dim cmd As SqlCommand
Dim rdr As SqlDataReader
Dim da As SqlDataAdapter
Private Const cs As String = "ConnectionString"
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
con = New SqlConnection(cs)
con.Open()
cmd = New SqlCommand("select * from [dbo].[Item_Details]", con)
rdr = cmd.ExecuteReader()
While rdr.Read
ListBox1.Items.Add(rdr(1))
End While
con.Close()
End Sub
Private Sub ListBox1_MouseClick(sender As Object, e As MouseEventArgs) Handles ListBox1.MouseClick
Try
con = New SqlConnection(cs)
con.Open()
da = New SqlDataAdapter("Select * from Item_Details where itemname='" & ListBox1.SelectedItem.ToString() & "'", con)
Dim dt As New DataTable
da.Fill(dt)
For Each row As DataRow In dt.Rows
TextBox1.Text = row(0).ToString()
TextBox2.Text = row(1).ToString()
TextBox3.Text = row(2).ToString()
Dim data As Byte() = row(3)
Dim ms As New MemoryStream(data)
PictureBox1.Image = Image.FromStream(ms)
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
End Class

VB.Net, Problem updating table from DataGridView

This is my first post so forgive me if I goof!
I am trying to update myself from VBA to VB.Net. Using loads of help from Google etc I am doing Ok except when I try to update my table from a DataGridView. It just does not update. What I would like is that a cell is update on change. My code so far is shown (I have tried all sorts of builder, tables etc so my code may have a smattering of these that are redundant):
Imports System.Data.SqlClient
Imports System.IO
Imports Microsoft.SqlServer
Public Class FrmData
Private dsS As DataSet = New DataSet
Private adpS As SqlDataAdapter
Private builder As SqlCommandBuilder
Private bsource = New BindingSource
Private Sub FrmData_Load(sender As Object, e As EventArgs) Handles
MyBase.Load
Dim sqlS = "SELECT [Data].[Date] AS [Date] ,
[Data].[PaidBy] AS [Paid By] ,
[Data].[PaidAmount] AS [Paid Amount (£)],
[Data].[AmountLeft] AS [Amount Left (£)]
FROM [Data] WHERE [Data].[Name]= '" & strName & "'
ORDER BY [Data].[Date] DESC"
Dim adpS As SqlDataAdapter
adpS = New SqlDataAdapter(sqlS, connection)
builder = New SqlCommandBuilder(adpS)
Dim dTable As New DataTable
bsource.DataSource = dTable
bsource.EndEdit()
adpS.Fill(dTable)
connection.Close()
DataGridView1.DataSource = dTable
End Sub
Private Sub DataGridView1_CellEndEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellEndEdit
DataGridView1.EndEdit()
Dim dt As DataTable
dt = TryCast(DataGridView1.DataSource, DataTable)
Dim x As Integer = 0
If dt.GetChanges() Is Nothing Then
MessageBox.Show("The table contains no changes to save.")
Else
Dim builder = New SqlCommandBuilder(adpS)
Dim rowsAffected As Integer = adpS.Update(dt)
If rowsAffected = 0 Then
MessageBox.Show("No rows were affected by the save operation.")
Else
MessageBox.Show(rowsAffected & " rows were affected by the save operation.")
End If
End If
End Sub
End Class
Any help would be appreciated.
This is for SQL Server, right. Try it like this.
Imports System.Data.SqlClient
Public Class Form1
Dim sCommand As SqlCommand
Dim sAdapter As SqlDataAdapter
Dim sBuilder As SqlCommandBuilder
Dim sDs As DataSet
Dim sTable As DataTable
Private Sub load_btn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles load_btn.Click
Dim connectionString As String = "Data Source=.;Initial Catalog=pubs;Integrated Security=True"
Dim sql As String = "SELECT * FROM Stores"
Dim connection As New SqlConnection(connectionString)
connection.Open()
sCommand = New SqlCommand(sql, connection)
sAdapter = New SqlDataAdapter(sCommand)
sBuilder = New SqlCommandBuilder(sAdapter)
sDs = New DataSet()
sAdapter.Fill(sDs, "Stores")
sTable = sDs.Tables("Stores")
connection.Close()
DataGridView1.DataSource = sDs.Tables("Stores")
DataGridView1.ReadOnly = True
save_btn.Enabled = False
DataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect
End Sub
Private Sub new_btn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles new_btn.Click
DataGridView1.[ReadOnly] = False
save_btn.Enabled = True
new_btn.Enabled = False
delete_btn.Enabled = False
End Sub
Private Sub delete_btn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles delete_btn.Click
If MessageBox.Show("Do you want to delete this row ?", "Delete", MessageBoxButtons.YesNo) = DialogResult.Yes Then
DataGridView1.Rows.RemoveAt(DataGridView1.SelectedRows(0).Index)
sAdapter.Update(sTable)
End If
End Sub
Private Sub save_btn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles save_btn.Click
sAdapter.Update(sTable)
DataGridView1.[ReadOnly] = True
save_btn.Enabled = False
new_btn.Enabled = True
delete_btn.Enabled = True
End Sub
End Class
After two days working on this, I finally got it right for myself! Also, I had an eye on #ryguy72 codes as well. these are the steps you can take to get there:
Step 1: Drag and drop DataGridView into your form
Step 2: In the App.config add this between configuration:
<connectionStrings>
<add name="ehsanConnection" connectionString="Data Source=XXX
; User= XX; Password= XXX" ProviderName="System.Data.SqlClient"/>
</connectionStrings>
Step 3: The code below shows how you can get the DataGridView programmatically right, it worked perfectly fine for me.
Dim sCommand As SqlCommand
Dim sAdapter As SqlDataAdapter
Dim sBuilder As SqlCommandBuilder
Dim sDs As DataSet
Dim sTable As DataTable
Dim connStr As String =
ConfigurationManager.ConnectionStrings("ehsanConnection").ToString
Dim connStri = New SqlConnection(connStr)
Dim sql As String = "SELECT * FROM [Ehsan].[dbo].[Data]"
sCommand = New SqlCommand(sql, connStri)
sAdapter = New SqlDataAdapter(sCommand)
sBuilder = New SqlCommandBuilder(sAdapter)
sDs = New DataSet()
sAdapter.Fill(sDs, "Data")
sTable = sDs.Tables("Data")
connStri.Close()
DataGridView1.DataSource = sDs.Tables("Data")
The main point here was that I had to use [Ehsan].[dbo].[Data] not only the name of the table, "Data". Actually, it didn't work for me that way and it kept complaining!
Step 4: If you want to update your database after you changed some of the records in datagridview, use this code :
sAdapter.Update(sDs.Tables(0))
Main important point is that: "you have to set a primary key in your table first otherwise it won't work!"

Displaying Data from SQL in TextBox by clicking ComboBox item in Visual Basic 2012

I have three columns in SQL, which I want the data displayed in three textboxes by clicking an item in ComboBox.
The issue is not really displaying. I can save the data fine and display. However, one of the text fields will only show one cell and not update when a different item is selected. Hope this is making sense.
Here is the code I have for saving:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim myconnect As New SqlClient.SqlConnection
myconnect.ConnectionString = "Data Source=.\INFLOWSQL;Initial Catalog=RioDiary;Integrated Security=True"
Dim mycommand As SqlClient.SqlCommand = New SqlClient.SqlCommand()
mycommand.Connection = myconnect
mycommand.CommandText = "INSERT INTO MyDiary (Title, DiaryContent, DiaryDate) VALUES (#Title, #DiaryContent, #DiaryDate)"
myconnect.Open()
Try
mycommand.Parameters.Add("#Title", SqlDbType.VarChar).Value = TextBox1.Text
mycommand.Parameters.Add("#DiaryContent", SqlDbType.VarChar).Value = TextBox2.Text
mycommand.Parameters.Add("#DiaryDate", SqlDbType.VarChar).Value = TextBox3.Text
mycommand.ExecuteNonQuery()
MsgBox("Success")
Catch ex As System.Data.SqlClient.SqlException
And here is the code for displaying in form1:
Imports System.Data.SqlClient
Public Class Form1
Dim con As New SqlConnection
Dim ds As New DataSet
Dim da As New SqlDataAdapter
Dim sql As String
Dim inc As Integer
Dim MaxRows As Integer
Dim max As String
Dim dt As New DataTable
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'RioDiaryDataSet5.MyDiary' table. You can move, or remove it, as needed.
Me.MyDiaryTableAdapter.Fill(Me.RioDiaryDataSet5.MyDiary)
Dim con As New SqlConnection(" Data Source=.\INFLOWSQL;Initial Catalog=RioDiary;Integrated Security=True")
Dim cmd As New SqlCommand("Select Title,DiaryContent,DiaryDate FROM MyDiary ")
Dim da As New SqlDataAdapter
da.SelectCommand = cmd
cmd.Connection = con
da.Fill(ds, "MyDiary")
con.Open()
ComboBox1.DataSource = ds.Tables(0)
ComboBox1.DisplayMember = "Title'"
ComboBox1.ValueMember = "DiaryContent"
End Sub
Private Sub NewEntryToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles NewEntryToolStripMenuItem.Click
AddEntry.Show()
End Sub
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
If (Not Me.ComboBox1.SelectedValue Is Nothing) Then
Me.TextBox2.Text = ComboBox1.Text
Me.TextBox3.Text = ComboBox1.SelectedValue.ToString
End If
End Sub
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
If dt.Rows.Count > 0 Then
TextBox1.Text = dt.Rows(0)("DiaryDate").ToString() 'Where ColumnName is the Field from the DB that you want to display
End If
End Sub
End Class
As you can see from the code, I want to display Title and DiaryContent in two separate textboxes by clicking on Title in the Combobox. This works fine.
The issue I have is DiaryDate only shows the first entry and does not update when selecting the Item from ComboBox.
Can anyone help?
You can try to play with ComboBox's SelectedItem property. Since ComboBox's DataSource is DataTable here, SelectedItem of ComboBox represent a row in DataTable. Given DataRow in hand, you can display value of any column of DataRow in TextBoxes :
........
If (Not Me.ComboBox1.SelectedItem Is Nothing) Then
Dim SelectedItem = TryCast(comboBox1.SelectedItem, DataRowView)
Me.TextBox1.Text = SelectedItem.Row("Title").ToString()
Me.TextBox2.Text = SelectedItem.Row("DiaryContent").ToString()
Me.TextBox3.Text = SelectedItem.Row("DiaryDate").ToString()
End If
........
Public Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim cn As New SqlClient.SqlConnection("Data Source=thee-pc;Initial Catalog=jobportal;Integrated Security=True")
Dim cmd As New SqlClient.SqlCommand
Dim tbl As New DataTable
Dim da As New SqlClient.SqlDataAdapter
Dim reader As SqlClient.SqlDataReader
Try
cn.Open()
Dim sql As String
sql = "select * from Register"
cmd = New SqlClient.SqlCommand(sql, cn)
reader = cmd.ExecuteReader
While reader.Read
Dim id = reader.Item("cid")
ComboBox1.Items.Add(id)
End While
cn.Close()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
Dim cn As New SqlClient.SqlConnection("Data Source=thee-pc;Initial Catalog=jobportal;Integrated Security=True")
Dim cmd As New SqlClient.SqlCommand
Dim tbl As New DataTable
Dim da As New SqlClient.SqlDataAdapter
Dim reader As SqlClient.SqlDataReader
Try
cn.Open()
Dim sql As String
sql = "select * from register where cid ='" + ComboBox1.Text + "'"
cmd = New SqlClient.SqlCommand(sql, cn)
reader = cmd.ExecuteReader
While reader.Read
TextBox1.Text = reader.Item("cname")
TextBox2.Text = reader.Item("dob")
End While
cn.Close()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub

Form.show() does not respond

I am writing a small postIt programm which should enable the user to send little notes to other computers using a database.
I have a main-Form where I can write messages and see users online, a sheet-form which should display messages and a sql database which has a table for users and messages.
The idea is that I am writing messages into the Messagestable and my programm uses SqlDependency to get the new messages and to show them in sheets. So far so good.
The problem is when I add a new Message to my table the SqlDependency fires an Event and my mainForm creates a new sheet which freezes after sheet.Show() is called. The mainForm keeps on running but my sheets always do not respond.
Here's my code:
DBListener:
Imports System.Data
Imports System.Data.Sql
Imports System.Data.SqlClient
Imports System.Threading
Public Class DBListener
Private changeCount As Integer = 0
Private Const tableName As String = "IMSMessages"
Private Const statusMessage As String = _
"{0} changes have occurred."
Private exitRequested As Boolean = False
Private waitInProgress As Boolean = False
Private recieverHost As String
Private imsMain As IMSMain
Public Sub New(main As IMSMain, recieverHost As String)
Me.imsMain = main
Me.recieverHost = recieverHost
initCommand(recieverHost)
SqlDependency.Start(connectionString)
GetMsg(recieverHost)
End Sub
Private connectionString As String = "Data Source=NB_RANDY\SQLEXPRESS;Initial Catalog=eurom_test;Integrated Security=SSPI;"
Private sqlConn As SqlConnection = New SqlConnection(connectionString)
Private commandMesg As SqlCommand = Nothing
Private commandUsers As SqlCommand = Nothing
Private Sub initCommand(recieverHost As String)
commandMesg = New SqlCommand
commandMesg.CommandText = "SELECT MessageID,SenderHost,RecieverHost,isRead,isRecieved,Stamp from dbo.IMSMessages " &
"WHERE RecieverHost=#RecieverHost" &
" AND isRecieved = 0"
commandMesg.Parameters.Add("#RecieverHost", SqlDbType.VarChar).Value = recieverHost
commandMesg.Connection = sqlConn
commandUsers = New SqlCommand
commandUsers.CommandText = "Select HostName From dbo.IMSUser"
End Sub
Private Sub OnChangeMsg(ByVal sender As System.Object, ByVal e As System.Data.SqlClient.SqlNotificationEventArgs)
Dim dep As SqlDependency = DirectCast(sender, SqlDependency)
RemoveHandler dep.OnChange, AddressOf OnChangeMsg
GetMsg(recieverHost)
End Sub
Private Sub OnChangeUser(ByVal sender As System.Object, ByVal e As System.Data.SqlClient.SqlNotificationEventArgs)
Dim dep As SqlDependency = DirectCast(sender, SqlDependency)
RemoveHandler dep.OnChange, AddressOf OnChangeUser
GetUsers()
End Sub
Public Sub GetMsg(recieverHost As String)
If Not sqlConn.State = ConnectionState.Open Then
sqlConn.Open()
End If
commandMesg.Notification = Nothing
Dim dep As SqlDependency = New SqlDependency(commandMesg)
AddHandler dep.OnChange, New OnChangeEventHandler(AddressOf OnChangeMsg)
Dim table As DataTable = New DataTable
Dim adapter As SqlDataAdapter = New SqlDataAdapter(commandMesg)
adapter.Fill(table)
imsMain.recieveNewMessages(table)
End Sub
Public Sub GetUsers()
If Not sqlConn.State = ConnectionState.Open Then
sqlConn.Open()
End If
commandMesg.Notification = Nothing
Dim dep As SqlDependency = New SqlDependency(commandUsers)
AddHandler dep.OnChange, New OnChangeEventHandler(AddressOf OnChangeUser)
Dim table As DataTable = New DataTable
imsMain.updateOnlineUserList()
End Sub
End Class
IMSMain-Form:
Imports System.Data.SqlClient
Imports System.Threading
Public Class IMSMain
Private user As IMSUser
Private listener As DBListener
Private sqlConn As SqlConnection
Public Sub New()
InitializeComponent()
sqlConn = New SqlConnection("Data Source=NB_RANDY\SQLEXPRESS;Initial Catalog=eurom_test;Integrated Security=SSPI;")
Me.user = New IMSUser(My.Computer.Name)
user.register()
updateOnlineUserList()
listener = New DBListener(Me, user.HostName)
End Sub
Private Sub onSend(sender As Object, e As EventArgs) Handles bt_send.Click
Dim command As SqlCommand = New SqlCommand
Dim msgText = tb_text.Text
Dim reciever As IMSUser = lb_Online.SelectedItem
Dim insert_string As String = "Insert INTO dbo.IMSMessages(Text,RecieverHost,SenderHost,isRead,isRecieved,Stamp) Values(#Text,#RecieverHost,#SenderHost,#isRead,#isRecieved,#Stamp)"
Dim adapter As SqlDataAdapter = New SqlDataAdapter
Dim table As DataTable = New DataTable()
Try
If Not sqlConn.State = ConnectionState.Open Then
sqlConn.Open()
End If
command.Connection = sqlConn
command.CommandText = insert_string
adapter.SelectCommand = command
adapter.Fill(table)
command.CommandText = insert_string
command.Parameters.Add("#Text", SqlDbType.VarChar).Value = msgText
command.Parameters.Add("#RecieverHost", SqlDbType.NChar).Value = reciever.HostName
command.Parameters.Add("#SenderHost", SqlDbType.NChar).Value = user.HostName
command.Parameters.Add("#isRecieved", SqlDbType.Bit).Value = 0
command.Parameters.Add("#isRead", SqlDbType.Bit).Value = 0
command.Parameters.Add("#Stamp", SqlDbType.SmallDateTime).Value = DateTime.Now
command.ExecuteNonQuery()
Catch ex As Exception
Console.WriteLine("onSend: internal database exception" + ex.Message)
End Try
End Sub
Private Sub processMessageId(refMessageID As Integer)
Dim command As SqlCommand = New SqlCommand
Dim msgID_string As String = "SELECT * from dbo.IMSMessages " &
"WHERE MessageID=#MessageID AND isRecieved = 0" &
" ORDER BY Stamp"
Dim isRecievedUpdate_string As String = "Update dbo.IMSMessages " &
"SET isRecieved=1" &
" WHERE MessageID=#MessageID"
Dim adapter As SqlDataAdapter = New SqlDataAdapter
Dim table As DataTable = New DataTable()
Try
If Not sqlConn.State = ConnectionState.Open Then
sqlConn.Open()
End If
command = New SqlCommand
command.CommandText = msgID_string
command.Parameters.Add("#MessageID", SqlDbType.Int).Value = refMessageID
command.Connection = sqlConn
adapter.SelectCommand = command
adapter.Fill(table)
command = New SqlCommand
command.Connection = sqlConn
command.CommandText = isRecievedUpdate_string
command.Parameters.Add("#MessageID", SqlDbType.Int).Value = refMessageID
command.ExecuteNonQuery()
Catch ex As Exception
Console.WriteLine("processMessageID: internal database exception" + ex.Message)
End Try
Try
Dim row As DataRow = table.Rows(0)
Dim senderHost As String = row("SenderHost")
Dim sender As IMSUser = New IMSUser(senderHost)
Dim currentSheet As IMSSheet
Dim stringText As String = row("Text")
Dim stamp As Date = row("Stamp")
currentSheet = New IMSSheet(sender, stringText, stamp)
currentSheet.Show()
Catch ex As Exception
Console.WriteLine("processMessageID: error while showing sheet")
End Try
End Sub
Public Sub recieveNewMessages(newMessageTable As DataTable)
For Each row As DataRow In newMessageTable.Rows
Dim id As Integer = row("MessageID")
processMessageId(id)
Next
End Sub
Public Sub updateOnlineUserList()
lb_Online.Items.Clear()
Dim adapter As SqlDataAdapter = New SqlDataAdapter
Dim table As DataTable = New DataTable()
Dim command As SqlCommand = New SqlCommand
Dim onlineUser_string = "Select * FROM dbo.IMSUser"
command.CommandText = onlineUser_string
Try
If Not sqlConn.State = ConnectionState.Open Then
sqlConn.Open()
End If
command.Connection = sqlConn
adapter.SelectCommand = command
adapter.Fill(table)
Catch ex As Exception
Console.WriteLine("internal database exception" + ex.Message)
End Try
For Each row As DataRow In table.Rows
Dim tmp As IMSUser = New IMSUser(row("HostName"))
If Not user.Equals(tmp) Then
lb_Online.Items.Add(tmp)
End If
Next
End Sub
End Class
IMSSheet-Form:
Public Class IMSSheet
Dim IsDraggingForm As Boolean = False
Private MousePos As New System.Drawing.Point(0, 0)
Public Sub New(session As IMSUser, text As String, stamp As Date)
Ini
tializeComponent()
Me.tb_sender.Text = session.HostName
addText(text, stamp)
End Sub
Private Sub addText(msg As String, stamp As DateTime)
Dim currentText As String = tb_text.Text
currentText = currentText + stamp.ToString + Environment.NewLine + msg + Environment.NewLine
tb_text.Text = currentText
End Sub
Private Sub IMSSheet_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseDown
If e.Button = MouseButtons.Left Then
IsDraggingForm = True
MousePos = e.Location
End If
End Sub
Private Sub IMSSheet_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseUp
If e.Button = MouseButtons.Left Then IsDraggingForm = False
End Sub
Private Sub IMSSheet_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles MyBase.MouseMove
If IsDraggingForm Then
Dim temp As Point = New Point(Me.Location + (e.Location - MousePos))
Me.Location = temp
temp = Nothing
End If
End Sub
Private Sub onClose(sender As Object, e As EventArgs) Handles bt_Close.Click
Me.Close()
End Sub
Private Sub bt_minimize_Click(sender As Object, e As EventArgs) Handles bt_minimize.Click
Me.WindowState = FormWindowState.Minimized
End Sub
Private Sub bt_Close_MouseHover(sender As Object, e As EventArgs) Handles bt_Close.MouseHover
End Sub
Private Sub bt_minimize_MouseHover(sender As Object, e As EventArgs) Handles bt_minimize.MouseHover
End Sub
End Class
Interesting is that if I have already some new Messages in my Messagestable before I run the programm they are going to be displayed correctly.
If I display the sheets using Form.ShowDialog() it works as well but its not how I want it to work.
As I am out of ideas I hope you can help me.
You are running into issues because the change event of SqlDependency occurs on a different thread that your UI thread. From the SqlDepending documentation:
The OnChange event may be generated on a different thread from the
thread that initiated command execution.
When calling sheet.Show() on a non UI thread, Show() will lockup because there is no message loop to handle the UI events. Use Invoke() on ImsMain to create and show the ImsSheet on your UI thread.

DataGridView and BindingSource timer issue

I have a DataGridview that displays the data and a TextBox that allows me to filter the BindingSource with an SQL query to display the data based on the input string. This is all working fine apart from once I have filtered the DataGridView the timer function I have is resetting it back so all the data is being displayed again. The timer is set on a 1000ms basis, so it will show the filtered result for a second, then revert back.
Heres my code:
Imports System.Data.OleDb
Public Class Form1
Dim duraGadgetDB As String = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source = C:\Users\Dave\Documents\duraGadget.mdb;"
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim sql As String = "SELECT * FROM duragadget"
Dim connection As New OleDbConnection(duraGadgetDB)
Dim dataadapter As New OleDbDataAdapter(sql, connection)
Dim ds As New DataSet()
connection.Open()
dataadapter.Fill(ds, "dura")
connection.Close()
DataGridView1.DataSource = ds
DataGridView1.DataMember = "dura"
DataGridView1.Columns(5).Width = 300
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
insert.Show()
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Dim currentRowID As Integer
Dim scrollPosition As Integer = DataGridView1.FirstDisplayedScrollingRowIndex
Try
If DataGridView1.CurrentRow IsNot Nothing Then
currentRowID = DataGridView1.CurrentRow.Index
Dim sql As String = "SELECT * FROM duragadget"
Dim connection As New OleDbConnection(duraGadgetDB)
Dim dataadapter As New OleDbDataAdapter(sql, connection)
Dim ds As New DataSet()
connection.Open()
dataadapter.Fill(ds, "dura")
connection.Close()
DataGridView1.DataSource = ds
DataGridView1.DataMember = "dura"
DataGridView1.CurrentCell = DataGridView1.Item(1, currentRowID)
End If
Catch ex As Exception
End Try
DataGridView1.FirstDisplayedScrollingRowIndex = scrollPosition
End Sub
Private Sub txtSearchOnSku_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtSearchOnSku.TextChanged
Dim currentRowID As Integer
Dim scrollPosition As Integer = DataGridView1.FirstDisplayedScrollingRowIndex
Try
If DataGridView1.CurrentRow IsNot Nothing Then
currentRowID = DataGridView1.CurrentRow.Index
Dim sql As String = "SELECT * FROM duragadget"
Dim connection As New OleDbConnection(duraGadgetDB)
Dim dataadapter As New OleDbDataAdapter(sql, connection)
Dim ds As New DataSet()
Dim dsView As New DataView
Dim bs As New BindingSource()
connection.Open()
dataadapter.Fill(ds, "dura")
connection.Close()
dsView = ds.Tables(0).DefaultView
bs.DataSource = dsView
bs.Filter = "skuNo LIKE'" & txtSearchOnSku.Text & "*'"
DataGridView1.DataSource = bs
DataGridView1.CurrentCell = DataGridView1.Item(1, currentRowID)
End If
Catch ex As Exception
End Try
DataGridView1.FirstDisplayedScrollingRowIndex = scrollPosition
End Sub
End Class
Can anyone tell me how to stop this happening?
Assuming you mean that, if you have entered a value in your text box to filter your results, that you then don't want you timer to fire and unfilter them...
You can either, check the contents of the TextBox in the Timer1_Tick routine;
If txtSearchOnSku.Text <> "" Then Exit Sub
Or you can disable your timer in the txtSearchOnSku_TextChanged routine;
If txtSearchOnSku.Text <> "" Then
Timer1.Stop
Else
Timer1.Start
End If
Or, if you want to update your results once a second, based on you search, you can include the Filtering code in your Timer1_Tick routine.
As a quick point, you have alot of repeated code there. It may be worthwhile refactoring the repeated code out into another sub.