question

RogerSchlueter-7899 avatar image
0 Votes"
RogerSchlueter-7899 asked ·

Can't Get My Image to Appear in an Image Container

I have all the parts to display an image in the wpf Image control but I cant' get them all wired together. First I have a Picture class as follows ((ignoring irrelevant code):

Public Class Picture .... Private _Image As Byte() Private _Title As String End Class

I have a picture stored in a varbinarymax) field in an SQL Server database which I retrieve as follows (ignoring irrelevant code):

Dim pic As Picture
Using con As New SqlConnection(My.Settings.....)
Dim com As New SqlCommand("Get_Image", con) With ....}
com.Parameters.Add("@ImageID", SqlDbType.Int).Value = 3
con.Open()
Dim rdr As SqlDataReader = com.ExecuteReader
rdr.Read()
pic = New Picture With {.ImageID = rdr.GetInt32(0), .ImageDate = rdr.GetDateTime(1), .Title = rdr.GetString(2)}
Length = CInt(rdr.GetInt64(3))
MyData = New Byte(Length - 1) {}
rdr.GetBytes(4, 0, MyData, 0, Length)
End Using

Then I display it in the Image control named "picPerson"

Dim biImg As New BitmapImage()
Dim ms As New MemoryStream(MyData)
biImg.BeginInit()
biImg.StreamSource = ms
biImg.EndInit()
picPerson.Source = biImgDim biImg As New BitmapImage()
Dim ms As New MemoryStream(MyData)
biImg.BeginInit()
biImg.StreamSource = ms
biImg.EndInit()
picPerson.Source = biImg

Then I display it in the Image control named "picPerson"

Dim biImg As New BitmapImage()
Dim ms As New MemoryStream(MyData)
biImg.BeginInit()
biImg.StreamSource = ms
biImg.EndInit()
picPerson.Source = biImg

There is nothing displayed in picPerson but I also don't get any error messages or excepitons thrown. Where did I go off the rails?


Edit 1:

I appreciate all the effort you went to but it is to no avail. Line 42 gives a compile-time error. I have tried to rescue the ideas you have provided and now have this:

 Dim Length As Integer
         Dim MyData() As Byte
         Dim pic As Picture
         Using con As New SqlConnection(My.Settings.PIMConnectionString)
             Dim com As New SqlCommand("Get_Image", con) With {.CommandType = CommandType.StoredProcedure}
             com.Parameters.Add("@ImageID", SqlDbType.Int).Value = 3   'cp.PictureID
             con.Open()
             Dim rdr As SqlDataReader = com.ExecuteReader
             rdr.Read()
             pic = New Picture With {.ImageDate = rdr.GetDateTime(0), .Title = rdr.GetString(1)}
             Length = CInt(rdr.GetInt64(2))
             MyData = New Byte(Length) {}
             rdr.GetBytes(3, 0, MyData, 0, Length)
         End Using
         Dim biImg As New BitmapImage()
         Dim ms As New MemoryStream(MyData)
         ms.Read(MyData, 0, Length)
         biImg.BeginInit()
         biImg.StreamSource = ms
         biImg.EndInit()
         picPerson.Source = biImg


Unfortunately, this yields this run-time error:

The image cannot be decoded. The image header might be corrupted.

There is no need to provide a complete solution. I'm pretty sure the code listed above is where the problem is. Please take a look to see what is wrong.

windows-wpf
· 5
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi, which is Line 42?

0 Votes 0 ·

Line 42 in your view model

0 Votes 0 ·

Hi Roger, the 42. line " Dim ms As New MemoryStream(buf)" cannot raise error "The image cannot be decoded. The image header might be corrupted.", see documentation of MemoryStream.

0 Votes 0 ·
Show more comments
PeterFleischer-3316 avatar image
0 Votes"
PeterFleischer-3316 answered ·

Hi Roger, try following demo:

XAML:

 <Window x:Class="Window001"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:local="clr-namespace:WpfApp1"
         mc:Ignorable="d"
         Title="Demo load picture from database" Height="450" Width="800">
   <Window.DataContext>
     <local:Window001VM/>
   </Window.DataContext>
   <Grid>
     <Grid.ColumnDefinitions>
       <ColumnDefinition/>
       <ColumnDefinition/>
     </Grid.ColumnDefinitions>
     <Image Source="{Binding Picture}"/>
     <StackPanel Grid.Column="1">
       <Button Content="Prepare Database" Command="{Binding Cmd}" CommandParameter="Create" Margin="5"/>
       <Button Content="Load Picture" Command="{Binding Cmd}" CommandParameter="Load" Margin="5"/>
     </StackPanel>
   </Grid>
 </Window>

ViewModel:

 Imports System.ComponentModel
 Imports System.Data
 Imports System.Data.SqlClient
 Imports System.IO
 Imports System.Runtime.CompilerServices
    
 Public Class Window001VM
   Implements INotifyPropertyChanged
    
   Public Property Picture As BitmapImage
    
   Public ReadOnly Property Cmd As ICommand = New RelayCommand(AddressOf CmdExec)
    
   Private Sub CmdExec(obj As Object)
     Select Case obj.ToString
       Case "Create"
         Using cn As New SqlConnection(My.Settings.cnSQL)
           cn.Open()
           Using cmd As New SqlCommand With {.Connection = cn}
             ' delete previous table in SQL Server 2016 and above
             'cmd.CommandText = "DROP TABLE IF EXISTS Table1;"
             ' delete previous table in previous versions of SQL server 2016
             cmd.CommandText = "If OBJECT_ID('Table1', 'U') IS NOT NULL DROP TABLE IF EXISTS Table1;"
             Debug.Print($"Return value Drop: {cmd.ExecuteNonQuery}")
             ' Cretae Table
             cmd.CommandText = "CREATE Table Table1([ID] Integer Identity, [Picture] image, CONSTRAINT [PK_Table1] PRIMARY KEY ([ID]));"
             Debug.Print($"Return value Create Table: {cmd.ExecuteNonQuery}")
             ' Insert Record with Picture from file system
             cmd.CommandText = "INSERT Table1([Picture]) VALUES(@pict);"
             cmd.Parameters.Add("@pict", SqlDbType.Image).Value = File.ReadAllBytes("Image.jpg")
             Debug.Print($"Return value Insert Picture: {cmd.ExecuteNonQuery}")
           End Using
         End Using
       Case "Load"
         Using cn As New SqlConnection(My.Settings.cnSQL)
           cn.Open()
           Using cmd As New SqlCommand With {.Connection = cn}
             cmd.CommandText = "SELECT * FROM Table1;"
             Dim rdr = cmd.ExecuteReader
             rdr.Read()
             Dim buf = CType(rdr(1), Byte())
             Dim ms As New MemoryStream(buf)
             Dim img As New BitmapImage()
             img.BeginInit()
             img.StreamSource = ms
             img.EndInit()
             Picture = img
             OnPropertyChanged(NameOf(Picture))
           End Using
         End Using
     End Select
   End Sub
    
   Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
   Private Sub OnPropertyChanged(<CallerMemberName> Optional propName As String = "")
     RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propName))
   End Sub
    
 End Class


· 1 ·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@PeterFleischer-3316 Please see Edit 1 that I have added to my OP.

0 Votes 0 ·
AlexLi-MSFT avatar image
0 Votes"
AlexLi-MSFT answered ·

Hi,

Welcome to our Microsoft Q&A platform!

You can try the following code:



 reader.Read()
 Dim buf As MemoryStream = New MemoryStream(CType(reader(1), Byte()))
 picPerson.Source = BitmapFrame.Create(buf, BitmapCreateOptions.None, BitmapCacheOption.OnLoad)

Thanks.

· 1 ·
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

In the meantime I have solved the issue. Thanks for your input.

0 Votes 0 ·