0

i'm trying to get the image from SQL to picturebox using Listbox in in VB.

here is my sql sample table.

enter image description here

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.

enter image description here

and the code I'm working with it give me this error: enter image description here

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
2
  • Your Form1_Load method is not correctly disposing of your DB connection resources. Commented Oct 8, 2021 at 3:08
  • Use a SqlDataReader and its GetSqlBinary() method to read binary/varbinary columns. You should not be using the obsolete image column data-type. Commented Oct 8, 2021 at 3:09

2 Answers 2

2

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.

enter image description here

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
Sign up to request clarification or add additional context in comments.

3 Comments

there is a slight problem I am having, whenever I execute or add another item in the listbox, the listbox doesnt update the items unless I restart the form again. I tried duplicating the form_load and the selectedindex event in a button, so whenever I click the button it runs the code again but it doesn't seems so work.
@PotatoPythonLearner I should have asked you to provide a new question but I just added an answer as an edit.
this is great! thank you soo much!
0

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

3 Comments

@potato python Learner This code will be useful to you
i don't know. it doesn't seem to show the picture from the sql to picturebox of the selecteditem in the listbox
Hi @potato python Learner Did you tried with this code? It's working like what you are expecting.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.