How does one go about loading images into the datacarousel?
My images are stored on SQL 2000 using the image type. There is also a integer field for Employee ID.
The datacarousel datasource is from a LINQ query. The EmployeeID loads fine but the images don't display I get binary numbers only.
Hello,
I believe that the images are being retrieved as a Byte[]. This needs to be converted to an image format that the XamDataCarousel can display. You could do this conversion before you bind the data to the XamDataCarousel.
The following code snippet will convert the images from NorthWind to a BitmapImage which can be displayed by the XamDataCarousel:
public BitmapImage ImageFromBytes(Byte[] bytes){ MemoryStream stream = new MemoryStream(); // to work around quirk in Northwind database: int offset = 78; stream.Write(bytes, offset, bytes.Length - offset); // end workaround BitmapImage image = new BitmapImage(); image.BeginInit(); image.StreamSource = stream; image.EndInit(); return image;}
You can use something like the above code to convert your images so that they can be displayed.
Let me know if you have any questions with this matter.
Alan
How do I do the bitmap conversion here? - My images appear to be retrieved as System.Data.Linq.Binary:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var EmployeeQuery = from q in ctx.tblEmployeeInfos
select q; //EmpID int, EmpImage image, EmpName string,
this.xamDataCarousel1.DataSource = EmployeeQuery;
}
I have been writing a test app for the carousel that had both a horizontal and vertical item path'd carousel and when I was using the actual image (stored on my C: drive) and referencing the path, the 1st carousel took it ok and the second one failed because it said they were already in use....so if this is a similar case, then I would say always load it into a MemoryStream and go from there.
A note about storing it into sql or store the path.....when you store just the path, you run into issues of some end user switching the path and unknowingly totally wrecking your app. However, if you store them in the Database...ex: sql 2005 express, it has a size limit of 4GB per database, so if you are putting large images/documents into it, it could fill up quite quickly. ***There's no size limit on a full version of sql 2005...just express. We are using express for most of our deployment and when the size gets close to the limit, we branch off to another database and we have another 4GB to use.
There's some pros and cons to both ways, but I would suggest for dummy proofing your code/design, store them in the database. Some people say this is a performance hog, but I haven't run into that issue yet...just the size limit.
-Jeremy
Thank you! - sixbitslocum & Jeremy's solutions both worked for me!
My next question is what is the ideal/preffered way of doing SQL images w/Infragistics? .....such as: should I be reading the images from a file instead of from sql?...or store the image path instead of the actual image?
Here's how we did it:
PseduoCode:
Run through your returned dataset and read the byteArray of your image field to a MemoryStream, then push that to a BitmapImage object, then use Create a Windows.Controls.Image object and tie the source to the BitmapImage you just created.....then you should be good to go.
I have this in the Page_Loaded event
//Begin code
string connString = "Persist Security Info=False;Integrated Security=SSPI;database=YOURDATABASEHERE;server=.\\INSTANCENAMEHERE"; string commString = "select SomeTableID, BinaryDataField from dbo.SomeTable"; SqlCommand comm = new SqlCommand(); comm.CommandText = commString; comm.CommandType = System.Data.CommandType.Text; comm.Connection = new SqlConnection(connString); SqlDataAdapter da = new SqlDataAdapter(comm); DataTable dt = new DataTable(); try { da.Fill(dt); // we have to convert the byte array into an image. // first step is to create a column for the actual image dt.Columns.Add("Image", typeof(System.Windows.Controls.Image)); //next step is to get the Photo column into a byte array. foreach (DataRow dr in dt.Rows) { Byte[] myByteArray = (Byte[])dr["BinaryDataField"]; MemoryStream ms = new MemoryStream(myByteArray, 0, myByteArray.Length); ms.Write(myByteArray,0,myByteArray.Length); //Move to the head of the MemoryStream or it will fail ms.Seek(0, SeekOrigin.Begin); //Send the MemoryStream over to a BitmapImage BitmapImage bi = new BitmapImage(); bi.BeginInit(); bi.StreamSource = ms; bi.EndInit(); System.Windows.Controls.Image image = new System.Windows.Controls.Image(); image.StretchDirection = StretchDirection.Both; image.Stretch = Stretch.UniformToFill; image.Margin = new Thickness(4); //Assign the Image.source to the BitmapImage's Data image.Source = bi; dr["Image"] = image; } // remove the byte[] column. This is optional; you can simply hide it if you wish. dt.Columns.Remove(dt.Columns["BinaryDataField"]); //Assign the DataTable's DefaultView to the Datasource this.XamDataCarousel1.DataSource = dt.DefaultView;
//End code
I just used this, so I know it works.
Here's the Converter we wrote to solve this exact problem.
Public Class BinaryToImageConverter Implements IValueConverter Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert Dim binaryData As Binary = value If binaryData Is Nothing Then Return Nothing End If
Dim buffer() As Byte = binaryData.ToArray() If buffer.Length = 0 Then Return Nothing End If
Dim res As New BitmapImage() res.BeginInit() res.StreamSource = New System.IO.MemoryStream(buffer) res.EndInit() Return res End Function
Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack Dim source As BitmapImage = value If source Is Nothing Then Return Nothing End If If Not source.StreamSource Is Nothing AndAlso source.StreamSource.Length > 0 Then Return GetBytesFromStream(source.StreamSource) End If
Return Nothing End Function
Private Function GetBytesFromStream(ByVal stream As System.IO.Stream) As Binary stream.Position = 0 Dim res(stream.Length) As Byte Using reader As New System.IO.BinaryReader(stream) reader.Read(res, 0, CType(stream.Length, Integer)) End Using Return New Binary(res) End Function
End Class
Just set the converter when you define the field like this:
</igDP:Field>