Displaying image from a class attribute in a button - c#

i need to display an image which is from a class attribute inside a button, the binding doesn't work.
This is how i proceed:
i have a class Products that contains ProductImage of type system.drawable.image and some other strings.
XAML code :
<Button Content="{Binding ProductImage}" Name="ImageButton"></Button>
the button is showing with Content : System.Drawing.Bitmap in it.
any help Please.
EDIT : i found important to add the Window2.XAML.cs file
MySqlConnection connection = new MySqlConnection(ConnectionManager.ConnectionString);
try
{
connection.Open();
MySqlCommand command = new MySqlCommand("SELECT * FROM products", connection);
MySqlDataReader reader = command.ExecuteReader();
var list = new List<ProductsBLL>();
while (reader.Read())
{
ProductsBLL product = new ProductsBLL();
product.ProductId = (int) reader[0];
product.ProductName = (string) reader[1];
product.ProductReference = (string) reader[2];
product.ProductColor = (string) reader[3];
var imagems = (byte[]) reader[4];
MemoryStream ms = new MemoryStream(imagems);
product.ProductImage = System.Drawing.Image.FromStream(ms);
product.ProductDescription = (string) reader[5];
product.ProductUnitPrice = (decimal) reader[6];
product.ProductUnitInStock = (int) reader[7];
product.ProductUnitInCommand = (int) reader[8];
list.Add(product);
product = null;
}
ProductsListView.ItemsSource = list;
}
catch (Exception e)
{
MessageBox.Show(this, e.Message);
}
finally
{
if(connection.State == ConnectionState.Open)
connection.Close();
}

The type of your ProductImage property is currently System.Drawing.Image, which is WinForms, not WPF. A System.Drawing.Image can not be drawn directly by a WPF Image control.
You should change the property type to System.Windows.Media.ImageSource:
public ImageSource ProductImage { get; set; }
Now you would create an instance of either System.Windows.Media.Imaging.BitmapImage or
System.Windows.Media.Imaging.BitmapFrame as value of the property. Note that the BitmapCacheOption.OnLoad must be set, because you want to dispose of the stream right after loading the image.
byte[] imageBuffer = ...
using (var memoryStream = new MemoryStream(imageBuffer))
{
product.ProductImage = BitmapFrame.Create(
memoryStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
or
using (var memoryStream = new MemoryStream(imageBuffer))
{
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = memoryStream;
bitmapImage.EndInit();
product.ProductImage = bitmapImage;
}
Finally (as already said in the other answer) you would have to use an Image control as the Button's Content:
<Button Name="ImageButton">
<Image Source="{Binding ProductImage}" />
</Button>

Try to use Image control as place holder for Bitmap :
<Button Name="ImageButton">
<Image Source="{Binding ProductImage}" />
</Button>

Related

Double clicking the cell error "Unable to cast object of type 'System.DBNull' to type 'System.Byte[]'."}"

Please help with thank you
Error occurs as Unable to cast object of type 'System.DBNull' to type 'System.Byte[]'."
When i "SAVE" the GEM entry form without an "image" it works fine.
When i "SAVE" the GEM entry form with an "image" it works fine.
the error occurs from the "Gem" grid-view which views the list of Gems.
When i need to "UPDATE" gem record, i will DoubleClick the cell.
So if there is an existing and if i need to change the image and "UPDATE" it works..BUT
error appears when i need to "UPDATE" an Record which has no image the errors popsup at this line...As the image: enter image description here
and this is my stock entry Code:
private void btnsave_Click(object sender, EventArgs e)
{
try
{
conn.Close();
conn.Open();
String query;
if (pb1.Image == null)
{
query = "INSERT INTO Stock_Gems (Stock_Type,Stock_no,No_of_pieces,Gem_Type,Weight,Cost,Create_Date,Update_Date,UserID) VALUES(#Stock_Type,#stock_no,#No_of_pieces,#Gem_Type,#Weight,#Cost,#Created_Date,#Updated_Date,#User_Create)";
}
else
{
query = "INSERT INTO Stock_Gems VALUES(#Stock_Type,#stock_no,#No_of_pieces,#Gem_Type,#Weight,#image,#Cost,#Created_Date,#Updated_Date,#User_Create)";
}
SqlCommand command = new SqlCommand(query, conn);
command.Parameters.Add("#Stock_Type", SqlDbType.VarChar);
command.Parameters["#Stock_Type"].Value = Stock_Type.Text;
command.Parameters.Add("#stock_no", SqlDbType.VarChar);
command.Parameters["#stock_no"].Value = txtstock_no.Text;
command.Parameters.Add("#No_of_pieces", SqlDbType.Int);
command.Parameters["#No_of_pieces"].Value = txtno_of_peices.Text;
command.Parameters.Add("#Gem_Type", SqlDbType.NVarChar);
command.Parameters["#Gem_Type"].Value = txt_gems.Text;
command.Parameters.Add("#Weight", SqlDbType.Float);
command.Parameters["#Weight"].Value = txt_weight.Text;
if (pb1.Image != null)
{
MemoryStream stream = new MemoryStream();
pb1.Image.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] pic = stream.ToArray();
command.Parameters.Add("#image", SqlDbType.Binary);
command.Parameters["#image"].Value = pic;
}
command.Parameters.Add("#Cost", SqlDbType.Decimal);
command.Parameters["#Cost"].Value = txt_cost.Text;
command.Parameters.Add("#Created_Date", SqlDbType.DateTime);
command.Parameters["#Created_Date"].Value = label11.Text;
command.Parameters.Add("#Updated_Date", SqlDbType.DateTime);
command.Parameters["#Updated_Date"].Value = label11.Text;
command.Parameters.Add("#User_Create", SqlDbType.NVarChar);
command.Parameters["#User_Create"].Value = hello.Text;
command.ExecuteNonQuery();
conn.Close();
if (cmbStockType.SelectedIndex == 0)
_lastUG++;
else
_lastMG++;
saveLastNumbers();
MessageBox.Show("You've inserted successfully!", "Successful Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
this.Hide();
}
}
this is my gride-view code:
private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
S_Gems myForm = new S_Gems();
myForm.Stock_Type.Text = this.dataGridView1.CurrentRow.Cells[1].Value.ToString();
myForm.txtstock_no.Text = this.dataGridView1.CurrentRow.Cells[2].Value.ToString();
myForm.txtno_of_peices.Text = this.dataGridView1.CurrentRow.Cells[3].Value.ToString();
myForm.txt_gems.Text = this.dataGridView1.CurrentRow.Cells[4].Value.ToString();
myForm.txt_weight.Text = this.dataGridView1.CurrentRow.Cells[5].Value.ToString();
byte[] pic = (Byte[])dataGridView1.CurrentRow.Cells[6].Value;
MemoryStream stream = new MemoryStream(pic);
myForm.pb1.Image = Image.FromStream(stream);
myForm.txt_cost.Text = this.dataGridView1.CurrentRow.Cells[7].Value.ToString();
// myForm.label11.Text = this.dataGridView1.CurrentRow.Cells[8].Value.ToString();
// myForm.label11.Text = this.dataGridView1.CurrentRow.Cells[9].Value.ToString();
myForm.ShowDialog();
}
And i am using an sql server 2014:
my gem entry table looks as:
Column Names:
ID|Stock_Type|Stock_No|No_of_pieces|Gem_Type|Weight|Image|Cost|Create_Date|Update_Date|UserID|
Datatype for Image is varbinary(MAX)
i have ticked the Allow NUlls
Elements that have no picture have a NULL value in the db in that column. So dataGridView1.CurrentRow.Cells[6] does not contain a byte[] representing the image, but is DBNull.Value.
Your code should be aware of this possibility and skip the image processing:
if (dataGridView1.CurrentRow.Cells[6] is byte[] pic) // C#7
{
MemoryStream stream = new MemoryStream(pic);
myForm.pb1.Image = Image.FromStream(stream);
}
else
myForm.pb1.Image = null;
Before C#7 you shoud do
byte[] pic = dataGridView1.CurrentRow.Cells[6] as byte[];
if (pic != null)
{
MemoryStream stream = new MemoryStream(pic);
myForm.pb1.Image = Image.FromStream(stream);
}
else
myForm.pb1.Image = null;

How to add MapChildren for each element in a Collection in Windows Phone 8.1 project using C#?

I am a beginner in Windows Phone development, while trying to develop a map based application, I am stuck how to add a MapIcon or any MapChildren for a no. of locations stored in a database file.
I have successfully retrieved the data collection from the database, further i don't know how to add a mapIcon for each entry
try
{
double latitude = myposition.Coordinate.Point.Position.Latitude;
double longitude = myposition.Coordinate.Point.Position.Longitude;
Collection bins = new Collection(); //collection of class Dustbin
bins = DustbinViewModel.GetDefault().GetItem(latitude, longitude); //database query using ViewModels..It is working
msgbox = new MessageDialog("Dustbins retrieved");
await msgbox.ShowAsync();
string msg = "";
foreach (Dustbin d in bins)
{
msg = msg + d.Id + "\n";
}
msgbox = new MessageDialog(msg); //Just for checking whether the data is recieved or not
await msgbox.ShowAsync();
int i = 1;
foreach (Dustbin d in bins)
{
Geopoint point = new Geopoint(new BasicGeoposition
{
Latitude = d.Latitude,
Longitude = d.Latitude
});
/*var shape = new MapIcon
{
Title = "Dustbin:" + i,
Location = point,
Image = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/dustbin.png")),
NormalizedAnchorPoint = new Point(0.5, 0.5),
ZIndex = 5,
};
MyMap.MapElements.Add(shape);*/
Image image = new Image();
image.Width = 40;
image.Height = 40;
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.UriSource = new Uri("ms-appx:///Assets/location.png");
image.Source = bitmapImage;
MapControl.SetLocation(image, point);
MapControl.SetNormalizedAnchorPoint(image, new Point(0.25, 0.9));
MyMap.Children.Add(image);
i++;
}
}
catch(Exception ex)
{
msgbox = new MessageDialog("Something went wrong !! Please try again later."+ex.Message);
await msgbox.ShowAsync();
}
As I am new to this field, I will be thankful to your answers..
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.UriSource = new Uri("ms-appx:///Assets/location.png");
image.Source = bitmapImage;
MapControl.SetLocation(image, point);
MapControl.SetNormalizedAnchorPoint(image, new Point(0.25, 0.9));
MyMap.Children.Add(image);
Just add
MapControl.SetLocation(bitmapImage, point);
MyMap.Children.Add(bitmapImage);
MapControl.SetNormalizedAnchorPoint(bitmapImage, new Point(0.25, 0.9));

Retrieving multiple images from database

So I'm working on my first project and right now there's something that's driving me a little bit crazy and I've been searching but I can't seem to find an answer.
I have two tables in my database, one is for the employee data (employeedata), and another only with pictures from their house (housepictures) with only three fields (PhotoID,EmployeeID,Photo), using a foreign key to the EmployeeID from the employeedata table.
I'm trying to retrieve the pictures from this table and put them in their respectives PictureBox (there are six in total, since I'm only storing 6 images for employee), but I've only managed to either retrieve the first picture, or the last, or the first picture and repeat it (this same photo) in every PictureBox. This is my current code:
try
{
using (MySqlConnection conn = new MySqlConnection(connDB.connstring))
{
using (MySqlCommand cmd = new MySqlCommand("select HousePicture from Employees.housepictures where EmployeeID='" + id + "'", conn))
{
conn.Open();
using (MySqlDataReader dr = cmd.ExecuteReader())
{
if (dr.Read())
{
PictureBox[] pb = { pictureBoxHouse1, pictureBoxHouse2, pictureBoxHouse3, pictureBoxHouse4, pictureBoxHouse5, pictureBoxHouse6 };
for (int i = 0; i < pb.Length; i++)
{
using (MemoryStream stream = new MemoryStream())
{
if (dr["HousePicture"] != DBNull.Value)
{
byte[] image = (byte[])dr["HousePicture"];
stream.Write(image, 0, image.Length);
Bitmap bitmap = new Bitmap(stream);
pb[i].Image = bitmap;
}
}
}
}
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Any suggestions would be very much appreciated!
Try getting your results first, then using while (instead of if) to loop through all those returned records. You can leave most of your code as-is, and increment a counter on each iteration of your loop, in order to set the correct PictureBox in your array.
PictureBox[] pb = { pictureBoxHouse1, pictureBoxHouse2, pictureBoxHouse3,
pictureBoxHouse4, pictureBoxHouse5, pictureBoxHouse6 };
using (MySqlDataReader dr = cmd.ExecuteReader())
{
int i = 0;
while (dr.Read())
{
using (MemoryStream stream = new MemoryStream())
{
if (dr["HousePicture"] != DBNull.Value)
{
byte[] image = (byte[])dr["HousePicture"];
stream.Write(image, 0, image.Length);
Bitmap bitmap = new Bitmap(stream);
pb[i].Image = bitmap;
}
}
i++;
}
}

What is wrong with my Tile creating and loading?

I've made a application that uses live tiles. I get it to work with the backgroundtask, it shows correct message but the image is completely black...
Here is my code where I save the image to /Shared/ShellContent/:
public MainPage()
{
InitializeComponent();
CurrentPlaceList = new ObservableCollection<CurrentPlaceListItemModel>();
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
var bmp = new WriteableBitmap(173, 173);
var weatherImage = new BitmapImage(new Uri("/Images/WeatherIcons/01d.png", UriKind.Relative));
var img = new Image { Source = weatherImage };
weatherImage.CreateOptions = BitmapCreateOptions.None;
var tt = new TranslateTransform();
tt.X = 0;
tt.Y = 0;
bmp.Render(img, tt);
bmp.Invalidate();
var filename = "/Shared/ShellContent/01d.jpg";
using (var st = new IsolatedStorageFileStream(filename, FileMode.OpenOrCreate, FileAccess.Write, store))
{
bmp.SaveJpeg(st, 173, 173, 0, 100);
}
}
StartAgent();
}
And where is my code where my ScheduledTask is supposed to update text and image, the images is completely black :(
protected override void OnInvoke(ScheduledTask task)
{
//TODO: Add code to perform your task in background
UpdateAppTile("-99");
NotifyComplete();
}
private void UpdateAppTile(string message)
{
ShellTile appTile = ShellTile.ActiveTiles.FirstOrDefault();
if (appTile != null)
{
StandardTileData tileData = new StandardTileData
{
Title = message,
BackgroundImage = new System.Uri("isostore:/Shared/ShellContent/01d.jpg", System.UriKind.Absolute)
};
appTile.Update(tileData);
}
}
This is taken from several tutorials, could anyone put a finger on what is wrong?
For me it looks like the image doesn't have enough time to load. I think the better way here is to do something like:
StreamResourceInfo streamImage = Application.GetResourceStream(uri.Uri);
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(streamImage.Stream);
Image image = new Image() { Width = uri.Width, Height = uri.Height, Source = bitmapImage };
Also, you can check out a MSP Toolkit that could generate tile for you (msptoolkit on NuGet).

Saving an Image file to sql Server and converting byte array into image

I am storing images in a database and would like to convert them from byte array to image. I have no problem converting an object to byte array but I get an error of "Parameter is not valid" when trying to convert from byte array to image. The object I am passing to my method is from a dataset row.
Stored procedure
USE [----------------]
GO
/****** Object: StoredProcedure [dbo].[usp_imageloader_add_test] Script Date: 01/16/2012 09:19:46 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[usp_imageloader_add_test]
#p_Image Image
as
INSERT into Test_Images VALUES(#p_Image)
Upload File control /convert Image file to byte array and save data to database
protected void btnUpload_Click(object sender, EventArgs e)
{
if (ctrlUpload.PostedFile != null)
{
if (ctrlUpload.PostedFile.ContentLength > 0)
{
// Get Posted File
HttpPostedFile objHttpPostedFile = ctrlUpload.PostedFile;
// Find its length and convert it to byte array
int ContentLength = objHttpPostedFile.ContentLength;
// Create Byte Array
byte[] bytImg = new byte[ContentLength];
// Read Uploaded file in Byte Array
objHttpPostedFile.InputStream.Read(bytImg, 0, ContentLength);
using (SqlConnection dbConnection = new SqlConnection(app_settings.sql_conn_string_db))
{
try
{
string sql = "usp_imageloader_add_test";
SqlCommand cmd = new SqlCommand(sql, dbConnection);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#p_Image", bytImg).SqlDbType = SqlDbType.Binary;
cmd.Connection.Open();
cmd.ExecuteNonQuery();
cmd.Connection.Close();
}
catch (Exception ex)
{
ex.Message.ToString();
}
}
}
}
}
Table method which calls objToImg method
protected void Page_Load(object sender, EventArgs e)
{
generateTable(false);
}
private Table generateTable(bool flag)
{
Table tb = BuildList(GetData(), flag);
if (imgloadercms != null)
{
PlaceHolder ph = new PlaceHolder();
StringBuilder sb = new StringBuilder();
ph.Controls.Add(new LiteralControl(sb.ToString()));
}
imgloadercms.Controls.Add(tb);
return tb;
}
protected Table BuildList(DataTable tb, bool flag)
{
Table tblImageLibrary = new Table();
tblImageLibrary.BorderStyle = BorderStyle.Solid;
tblImageLibrary.BorderWidth = Unit.Pixel(8);
if (tb.Rows.Count > 0)
{
try
{
if (!flag)
{
tblImageLibrary.BorderColor = Color.Black;
tblImageLibrary.BorderWidth = Unit.Pixel(1);
TableRow tr = new TableRow(); // Table row for header of table
tr.BackColor = Color.LightBlue;
TableCell c1 = new TableCell();
TableCell c2 = new TableCell();
c1.Controls.Add(new LiteralControl("Image Id"));
tr.Cells.Add(c1);
c2.Controls.Add(new LiteralControl("Image"));
tr.Cells.Add(c2);
tblImageLibrary.Rows.Add(tr);
}
int i = 0;
foreach (DataRow r in tb.Rows) // Create new row foreach row in table
{
TableRow tr = new TableRow();
if (i % 2 == 0)
{
tr.BackColor = Color.LightYellow;
}
// Build cells
TableCell c1 = new TableCell();
TableCell c2 = new TableCell();
c2.Width = 300;
c1.Controls.Add(new LiteralControl(r["Image_Id"].ToString()));
tr.Cells.Add(c1);
// Call method to serialize obj to byte array
//System.Drawing.Image dbImg =
ObjToImg(r["Image_File"]);
}
catch (Exception ex)
{
ex.ToString();
}
if (!flag)
{
}
}
return tblImageLibrary;
}
Return Image
private System.Drawing.Image ObjToImg(object obj)
{
//byte[] byteArray = null;
if (obj == null)
return null;
else
{
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, obj); //now in Memory Stream
ms.ToArray(); // Array object
ms.Seek(0, SeekOrigin.Begin);
//return (System.Drawing.Image)bf.Deserialize(ms);
System.Drawing.Image myImage = (System.Drawing.Image)bf.Deserialize(ms);
return myImage;
}
Whenever I try to add the memory stream object to the image object constructor I get the error message of "Parameter is not valid". Maybe I made a mistake when insert the byte array into the database because I have looked at other code and it doesn't make sense how it's not working.
Try to deserialize the object first from byte array with your BinaryFormatter!
Try to use following two methods:
private System.Drawing.Image ObjToImg(byte[] obj)
{
if (obj == null)
return null;
else
{
BinaryFormatter bf = new BinaryFormatter();
using(MemoryStream ms = new MemoryStream(obj))
{
return (System.Drawing.Image)bf.Deserialize(ms);
}
}
}
private byte[] ImgToObj(System.Drawing.Image obj)
{
if (obj == null)
return null;
else
{
BinaryFormatter bf = new BinaryFormatter();
using(MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, obj);
return ms.ToArray();
}
}
}
I just recently had to do the exact same thing in VB.NET. Here is my code, run through Telerik's Code Converter. It was quite tricky to get working, and is still honestly a pain.
To upload an image:
private bool uploadImage(ref Bitmap p)
{
SqlConnection con = new SqlConnection();
con.ConnectionString = Configuration.ConfigurationManager.ConnectionStrings("ConnStringHere").ConnectionString;
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "INSERT INTO Table_Name (File2) VALUES (#File2)"; //I named the column File2 simply because "File" seemed to be a keyword in SQLServer
cmd.CommandType = CommandType.Text;
cmd.Connection = con;
SqlParameter File1 = new SqlParameter("#File2", SqlDbType.Image);
MemoryStream ms = new MemoryStream();
using (Bitmap tempImage = new Bitmap(p))
{
tempImage.Save(ms, p.RawFormat);
}
byte[] data = ms.GetBuffer();
if (!isValidImage(data)) //optional, will include code if requested.
{
return false;
}
File1.Value = data;
cmd.Parameters.Add(File1);
con.Open();
int result = cmd.ExecuteNonQuery();
if (result > 0)
{
// SUCCESS!
con.Close();
return true;
}
else
{
//failure
con.Close();
return false;
}
}
To retrieve an image:
private Bitmap retrieveBitmap()
{
Image image1 = null
if (dt1.Rows.Count > 0)
{
byte[] imageData1 = null;
if (dt1[0].Count > 0)
{
if (!Information.IsDBNull(dt1.CopyToDataTable()[0].Item("File2")))
{
imageData1 = (byte[])dt1.CopyToDataTable()[0].Item("File2");
}
}
if ((imageData1 != null))
{
if (isValidImage(imageData1))
{
using (MemoryStream ms = new MemoryStream(imageData1, 0, imageData1.Length))
{
ms.Write(imageData1, 0, imageData1.Length);
image1 = Image.FromStream(ms, true);
}
return image1;
}
else
{
// "Invalid image on server";
return null;
}
}
}
}
My code may need small formatting changes, please edit whatever has invalid syntax (my C# is a little rusty, and my code was run through a converter).

Categories