Click here to Skip to main content
15,893,588 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hi,
What im trying to do is display an image on a datagridview that has been converted from a base64String.My problem is it is displaying the same image for each row even though the base64String for each image is different. My code below shows that i have declared the ImageColumn first, then converted the Base64String into imageBytes in each row of the datagridview. What am i missing?

What I have tried:

C#
DataGridViewImageColumn ic = new DataGridViewImageColumn();
ic.HeaderText = "Img";
ic.Name = "cImg";
ic.Width = 100;
ic.DisplayIndex = 5;
dgvProducts.Columns.Add(ic);


foreach (DataGridViewRow row in dgvProducts.Rows)
{
  byte[] imageBytes = 
Convert.FromBase64String(row.Cells["Picture"].Value.ToString());
 using (MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
 {
     foreach (DataGridViewRow rows in dgvProducts.Rows)
     {
       ic.Image = Image.FromStream(ms, true);
     }
                    
 }
            
     if(ic.Image != null)
     {
        row.Height = ic.Width;
      }
Posted
Updated 27-Apr-16 5:10am
Comments
CHill60 27-Apr-16 10:36am    
The inner foreach is putting a single image onto all rows. Why have a second foreach?
BEBE2011 27-Apr-16 10:42am    
I have removed the inner foreach and its still the same?
Nigam,Ashish 27-Apr-16 10:37am    
you are not changing value/stream of image in loop.
BEBE2011 27-Apr-16 10:42am    
how would i change the value?
Nigam,Ashish 27-Apr-16 10:44am    
Can you mention whole function code.

1 solution

The problem is twofold: firstly as CHill60 has pointed out, you have a redundant inner loop:
C#
foreach (DataGridViewRow row in dgvProducts.Rows)
{
     byte[] imageBytes = Convert.FromBase64String(row.Cells["Picture"].Value.ToString());
     using (MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
     {
         foreach (DataGridViewRow rows in dgvProducts.Rows)
         {
             ic.Image = Image.FromStream(ms, true);
         }
The inner foreach doesn't even use the loop variable - so all it does is square the number of images you create.

The other problem is that you always put the created image in the same place:
C#
ic.Image = Image.FromStream(ms, true);
but since the value of ic is only ever set outside both loops, and you always set the image for the whole column you will always get the last image you load in every cell of the column!
Try this:
C#
foreach (DataGridViewRow row in dgvProducts.Rows)
    {
    byte[] imageBytes = Convert.FromBase64String(row.Cells["Picture"].Value.ToString());
    MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
    row.Cells["cImg"].Value = Image.FromStream(ms, true);

Note that you can't Dispose the stream inside the loop. The documentation is very clear that the stream must exist for the lifetime of the image: Image.FromStream Method (Stream, Boolean) (System.Drawing)[^]
Remarks
You must keep the stream open for the lifetime of the Image.


[edit]Forgot the Value property! :O [/edit]
 
Share this answer
 
v2
Comments
BEBE2011 27-Apr-16 11:27am    
Thanks, but im getting an error at this line row.Cells["cImg"] = Image.FromStream(ms, true) - ERROR : Cannot implicitly convert type 'System.Drawing.Image' to 'System.Windows.Forms.DataGridViewCell', So i tried - row.Cells["cImg"] = (DataGridViewCell)Image.FromStream(ms, true);
OriginalGriff 27-Apr-16 11:34am    
Ah - I forgot the Value property!
Fixed.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900