The problem is twofold: firstly as CHill60 has pointed out, you have a redundant inner loop:
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:
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:
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]