My question is about:
Here is my code for Database Connection (Successful code):
public static void getTableItems(DataTable dt, int bodySectionNo)
{
// gets the oledbconnection object to open and access
var con = GetConnection();
try
{
con.Open(); // opens db connection
// creates the sql query for db items change bodysection = # for different bodySections
OleDbCommand command = new OleDbCommand("SELECT itemNo, itemName, NSN, bodySection, Image.FileName, Image.FileData, Image.FileType FROM tblItems WHERE bodySection = " + bodySectionNo + ";", con);
OleDbDataAdapter oleAdapter = new OleDbDataAdapter(command); // executes the command and retrieves the data from the db
oleAdapter.Fill(dt); // fills the datatable with the query results
}
catch(Exception e)
{
// writes to console any errors for this connection
Console.WriteLine("ERROR: getTableItemsForHead, " + e.Message);
}
finally
{
con.Close(); // closes db connection
}
}
In my MainWindow.xaml.cs file I am trying to read through the datatable, store the data, and then pass the data into an element for the mainwindow to display. Here is my MainWindow.xaml.cs code (Unsuccessful code):
private void populateComboBox(DataTable dt, ComboBox cb)
{
foreach (DataRow row in dt.Rows)
{
WrapPanel wp = new WrapPanel();
TextBlock txtItemName = new TextBlock();
TextBlock txtNSN = new TextBlock();
Image img = new Image();
// creates a textbox and adds it to wrappanel
txtItemName.Text = Convert.ToString(row["itemName"]) + " ";
wp.Children.Add(txtItemName);
// creates a textbox and adds it to wrappanel
txtNSN.Text = Convert.ToString(row["NSN"]) + " ";
wp.Children.Add(txtNSN);
// stores image properties from datatable
var fileName = row["Image.FileName"];
var fileData = (byte[])row["Image.FileData"];
var fileType = row["Image.FileType"];
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.CreateOptions = BitmapCreateOptions.None;
bi.CacheOption = BitmapCacheOption.Default;
bi.StreamSource = new MemoryStream(fileData);
bi.EndInit();
img.Source = bi;
wp.Children.Add(img);
cb.Items.Add(wp);
}
}
I have tried multiple different ways to convert the byte[] to bitmap, bitmapimage, bitmapsource, image, imagesource, etc.. and I can not find the snippet to resolve this "No Imaging component suitable to complete this operation was found" It breaks on the bi.EndInit(); line.
System.NotSupportedException was unhandled by user code
HResult=-2146233067 Message=No imaging component suitable to complete this operation was found. Source=PresentationCore
StackTrace: at System.Windows.Media.Imaging.BitmapDecoder.SetupDecoderFromUriOrStream(Uri uri, Stream stream, BitmapCacheOption cacheOption, Guid& clsId, Boolean& isOriginalWritable, Stream& uriStream, UnmanagedMemoryStream& unmanagedMemoryStream, SafeFileHandle& safeFilehandle) at System.Windows.Media.Imaging.BitmapDecoder.CreateFromUriOrStream(Uri baseUri, Uri uri, Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, RequestCachePolicy uriCachePolicy, Boolean insertInDecoderCache) at System.Windows.Media.Imaging.BitmapImage.FinalizeCreation() at System.Windows.Media.Imaging.BitmapImage.EndInit() at CWEDA_take_1.SecondWindow.populateComboBox(DataTable dt, ComboBox cb) in P:\All Documents\BBMD 18\CWEDA EH\CWEDA Design 1\CWEDA take 1\SecondWindow.xaml.cs:line 286 at CWEDA_take_1.SecondWindow..ctor() in P:\All Documents\BBMD 18\CWEDA EH\CWEDA Design 1\CWEDA take 1\SecondWindow.xaml.cs:line 36
InnerException: ErrorCode=-2003292336 HResult=-2003292336 Message=The component cannot be found. (Exception from HRESULT: 0x88982F50) InnerException:
EDIT: file data that is in the byte[]
EDIT: SOLUTION!! I figured this out a bit ago, but forgot to upload my solution:
I had to determine the image type first by searching for the header block.
// Converts byte array from database to image source
public static BitmapImage convertByteSource(byte[] oleFieldBytes)
{
if (oleFieldBytes == null || oleFieldBytes.Length == 0) return null;
const string BITMAP_ID_BLOCK = "BM";
const string JPG_ID_BLOCK = "\u00FF\u00D8\u00FF";
const string PNG_ID_BLOCK = "\u0089PNG\r\n\u001a\n";
byte[] imageBytes;
// Get a UTF7 Encoded string version
Encoding u8 = Encoding.UTF7;
string strTemp = u8.GetString(oleFieldBytes);
// Get the first 300 characters from the string
string strVTemp = strTemp.Substring(0, 300);
// Search for the block
int iPos = -1;
if (strVTemp.IndexOf(BITMAP_ID_BLOCK) != -1)
iPos = strVTemp.IndexOf(BITMAP_ID_BLOCK);
else if (strVTemp.IndexOf(JPG_ID_BLOCK) != -1)
iPos = strVTemp.IndexOf(JPG_ID_BLOCK);
else if (strVTemp.IndexOf(PNG_ID_BLOCK) != -1)
iPos = strVTemp.IndexOf(PNG_ID_BLOCK);
else
throw new Exception("Unable to determine header size for the OLE Object");
// From the position above get the new image
if (iPos == -1)
throw new Exception("Unable to determine header size for the OLE Object");
//Array.Copy(
imageBytes = new byte[oleFieldBytes.LongLength - iPos];
MemoryStream ms = new MemoryStream();
ms.Write(oleFieldBytes, iPos, oleFieldBytes.Length - iPos);
imageBytes = ms.ToArray();
ms.Close();
// creates new bitmapimage
BitmapImage bi = new BitmapImage();
bi.BeginInit();// inits bitmapimage
bi.CreateOptions = BitmapCreateOptions.None;
bi.CacheOption = BitmapCacheOption.Default;
bi.StreamSource = new MemoryStream(imageBytes);
bi.EndInit();
return bi;
}
The code in this page looks somewhat different from what you have there:
http://csharphelper.com/blog/2015/07/display-images-in-an-access-database-in-wpf-and-c/
In case this works and the link breaks in the future. the code does:
if (reader.IsDBNull(6))
imgCover.Source = null;
else
imgCover.Source =
BytesToImage((byte[])reader.GetValue(6));
That method:
// Convert a byte array into a BitmapImage.
private static BitmapImage BytesToImage(byte[] bytes)
{
var bm = new BitmapImage();
using (MemoryStream stream = new MemoryStream(bytes))
{
stream.Position = 0;
bm.BeginInit();
bm.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
bm.CacheOption = BitmapCacheOption.OnLoad;
bm.UriSource = null;
bm.StreamSource = stream;
bm.EndInit();
}
return bm;
}
User contributions licensed under CC BY-SA 3.0