Search code examples
c#winformsdatagridviewdatagridviewimagecolumn

Changing image value in DataGridViewImageColumn does not remove previous image


The problem:

When changing what image shows up in the cell of a DataGridViewImageColumn, the previous image is still there behind the new image:

Example 1

(Note the red error behind the green checkmark)

What I have:

The image is showing status on connectivity to a machine. When the machine's status is updated an event is raised and the image is updated.

The declaration of the DataGridViewImageColumn:

DataGridViewImageColumn imc = new DataGridViewImageColumn
            {
                HeaderText = "C$",
                Name = "imc",
                Width = 25,
                ImageLayout = DataGridViewImageCellLayout.Stretch,
                ValuesAreIcons = true
            }; 

Defaults are set:

sDGView.Columns["imc"].DefaultCellStyle.NullValue = null;
((DataGridViewImageCell)sDGView.Rows[0].Cells["imc"]).Value = null;

Event when a row is added:

private void SDGView_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
        {
((DataGridViewImageCell)sDGView.Rows[LastRow].Cells["imc"]).Value = null;
        }

Method called when online status changed:

private void SetStatusImage(int ri)
        {
            var status = Core.Machines[ri].OnLine;

            //sDGView.Rows[ri].Cells["imc"].Dispose();

            var image = (DataGridViewImageCell)sDGView.Rows[ri].Cells["imc"];

            if (status is null)
            {
                image.Value = StatusImg[0];
            }
            else if (status is true)
            {
                image.Value = StatusImg[1];
            }
            else
            {
                image.Value = StatusImg[2];
            }
        }

The images:

public Icon[] StatusImg { get; private set; } = new Icon[]
        {
            Properties.Resources.Minus_Grey,
            Properties.Resources.Tick_Green,
            Properties.Resources.Error_Red
        };

What I've tried...

I've tried setting the image.Value to null - no change

I've called the Dispose() method on the cell itself and then created a new cell to take its place and set the value to the current image -- the previous image still shows up behind!

It seems each time I change the value of the cell, another image is simply added on top. I can verify by watching the memory size of the program increase as the image changes. The old one never actually goes away even with calling the Dispose() method.

Edit:

I tried having the main form call the Refresh() method in case it just needed to be redrawn. - no change

I tried removing the image variable and setting the image directly:

private void SDGView_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
        {
                            ((DataGridViewImageCell)sDGView.Rows[LastRow].Cells["imc"]).Value = StatusImg[0];
        }
private void SetStatusImage(int ri)
        {
            var status = Core.Machines[ri].OnLine;

            //sDGView.Rows[ri].Cells["imc"].Dispose();

            //var image = (DataGridViewImageCell)sDGView.Rows[ri].Cells["imc"];

            if (status is null)
            {
                //image.Value = StatusImg[0];
                ((DataGridViewImageCell)sDGView.Rows[ri].Cells["imc"]).Value = StatusImg[0];
            }
            else if (status is true)
            {
                //image.Value = StatusImg[1];
                ((DataGridViewImageCell)sDGView.Rows[ri].Cells["imc"]).Value = StatusImg[1];
            }
            else
            {
                //image.Value = StatusImg[2];
                ((DataGridViewImageCell)sDGView.Rows[ri].Cells["imc"]).Value = StatusImg[2];
            }


        }

--same result - previous image still persists behind the newly selected image.

Example 2

(Note the red error behind the green checkmark)


Solution

  • I tested such scenario with this simple code:

    private void PlanningDayPlans_Load(object sender, EventArgs e)
    {
        DataGridViewRow r = new DataGridViewRow();
        this.DataGridView1.Rows.Add(r);
    }
    
    private void Button1_Click(object sender, EventArgs e)
    {
        this.DataGridView1.Rows(0).Cells(0).Value = My.Resources.todo2;
    }
    
    private void Button2_Click(object sender, EventArgs e)
    {
        this.DataGridView1.Rows(0).Cells(0).Value = My.Resources.cross;
    }
    

    And it works without issues:

    enter image description here

    The pictures are PNG with transparent backgrounds (would show the problem), I can switch them back and forth and it works well.

    This is for un-bound and DataSource-less scenario.

    I think I know where your problem probably is created. You set the ValuesAreIcons property, which affects alpha channel of the background so that it is "correct" for icons. I would try to ommit this settings and use PNG icons, it will be fine.