Получить изображение из SQL с помощью Listbox в picturebox VB

#vb.net

Вопрос:

я пытаюсь перенести изображение из SQL в picturebox, используя Listbox в VB.

вот моя таблица примеров sql.

введите описание изображения здесь

и вот моя форма дизайна VB, поэтому я пытаюсь сделать следующее: когда я загружаю форму, если выбран элемент в списке, я хочу, чтобы он получал изображение(двоичные данные) из sql в picturebox в vb net.

введите описание изображения здесь

и код, с которым я работаю, выдает мне эту ошибку: введите описание изображения здесь

VB полный код:

 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    connect()
    Dim co As New SqlConnection("Data Source=WXCQSDQSDSQLEXPRESS;Initial Catalog=food;Integrated Security = True")
    co.Open()
    Dim com As New SqlCommand("SELECT Image from Items where ItemName = '" amp; ListBox1.SelectedIndex amp; "'", 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=WXCQSDQSDSQLEXPRESS;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
 

Комментарии:

1. Ваш Form1_Load метод неправильно распоряжается ресурсами подключения к БД.

2. Используйте a и его метод для чтения / записи. SqlDataReader GetSqlBinary() binary varbinary Вам не следует использовать устаревший image тип данных столбца.

Ответ №1:

Удалите поиск изображений из Form.Load . Мы выбрали все данные в GetDataFromSql функции. Волшебство происходит в ListBox1.SelectedIndexChanged методе.

Это SelectedIndexChanged будет происходить в результате кода в Form.Load и каждый раз, когда выбор меняется. Когда мы привязываем поле списка к источнику привязки, вся строка добавляется как a DataRowView . Мы можем использовать это для получения данных в столбце Изображение. Сначала проверьте, является ли поле пустым. Затем приведите к массиву байтов. Возьмите массив байтов и передайте его конструктору a MemoryStream . Потоки должны быть расположены так, чтобы они находились в Using блоке. Наконец, поток может быть присвоен Image свойству 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=WXCQSDQSDSQLEXPRESS;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
 

Редактировать

Я переключил код на базу данных, доступную для тестирования. Даже если это не ваша база данных, я уверен, что вы сможете следовать коду.

Вот схема моей базы данных.

введите описание изображения здесь

Главное отличие в том, что я переместил переменную DataTable на уровень класса, чтобы ее можно было увидеть из всех методов. Я сменил GetDataFromSql Sub его на «а». Он добавляет данные на уровень класса DataTable ( Bounddt ). AddItem Метод сначала получает Byte() данные из файла. Строка добавляется в DataTable массив Object с элементами, соответствующими таблице данных.

 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:UsersmaryoOneDriveDocumentsGraphicsAnimalssquirrel.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
 

Комментарии:

1. у меня есть небольшая проблема: всякий раз, когда я выполняю или добавляю другой элемент в поле списка, поле списка не обновляет элементы, если я снова не перезапущу форму. Я попытался дублировать событие form_load и selectedindex в кнопке, поэтому всякий раз, когда я нажимаю кнопку, она снова запускает код, но, похоже, это не работает.

2. @PotatoPythonLearner Я должен был попросить вас задать новый вопрос, но я просто добавил ответ в качестве правки.

3. это здорово! большое вам спасибо!

Ответ №2:

Импортирует систему.Данные.SqlClient Импортирует Систему.IO Форма публичного Класса1

 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='" amp; ListBox1.SelectedItem.ToString() amp; "'", 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
 

Конечный класс

Комментарии:

1. @ученик картофельного питона Этот код будет вам полезен

2. я не знаю. похоже, что изображение из поля sql в поле изображения выбранного элемента в списке не отображается

3. Привет @Ученик картофельного питона Ты пробовал с этим кодом? Это работает так, как вы ожидаете.