20

I have an existing application with a new requirement to show an image in a DataGridView cell to denote whether the record has a specific flag associated with it or not (not user editable, this comes from the DB).

If there is a flag, I show the corresponding image, and if there's no flag, I want nothing to be shown in the column.

The DataGridView columns weren't created in Visual Studio designer, or else this would easy. I could just set the NullValue property on the column. Instead the columns are created at runtime when all the data is loaded into a DataTable, and then a DataView is created from that DataTable, and then the DataGridView's Datasource is set to the DataView.

I can't completely rewrite this, or else I'd just define the columns in VS Designer instead of this ridiculous way of just letting the columns be defined from the DataTable.

My question is then, how can I make it so the column with the Images shows nothing when the underlying data table has a null?

Here's some pseudo C# to demonstrate what I mean. Remember, I didn't write it to use two DataTables like this; it was that way when I had it handed to me, and I don't want to make drastic changes just to add a new column...

DataTable rawData = someMethodThatReturnsMyRawData();
DataTable data = new DataTable();
data.Columns.Add("Flags", typeof(Image));
data.Columns.Add("SomeOtherColumn");

foreach (DataRow rawDataRow in rawData.Rows)
{
    DataRow dataRow = data.NewRow();
    bool hasFlagType1 = false;
    bool hasFlagType2 = false;

    if (rawDataRow["FlagType1ID"] != DBNull.Value)
    {
        hasFlagType1 = true;
    }

    if (rawDataRow["FlagType2ID"] != DBNull.Value)
    {
        hasFlagType2 = true;
    }

    if (hasFlagType1 && hasFlagType2)
    {
        dataRow[0] = Properties.Resources.BothFlagsImage;
    }
    else if (hasFlagType1)
    {
        dataRow[0] = Properties.Resources.FlagType1Image;
    }
    else if (hasFlagType2)
    {
        dataRow[0] = Properties.Resources.FlagType2Image;
    }
    else
    {
        //If neither flag set, I don't want it to show anything,
        //but if I leave it as null, a little box with an X in it shows up
        //I could set it to some transparent GIF here, but that seems lame
    }

    dataRow[1] = rawDataRow["SomeOtherColumn"];

    data.Rows.Add(dataRow);        
}

DataView dv = new DataView(data, string.Empty, "SomeOtherColumn ASC", DataViewRowState.CurrentRows);

this.emptyDataGridViewFromDesigner.DataSource = dv;

// How can I modify the column "Flags" at this point to show nothing if the value is null?

EDIT: Here's a screenshot so you can see what I mean by the little box with an X - those are all nulls...

DataGridView with Null Images

Also, it has to be .NET 3.5, so if there's a solution in .NET 4.0 only, I'm out of luck.

3 Answers 3

40

I figured this out...

Have to cast the column as a DataGridViewImageColumn, then set the DefaultCellStyle.NullValue for that column to null. From my example above, you'd do it like this...

((DataGridViewImageColumn)this.emptyDataGridViewFromDesigner.Columns["Flags"]).DefaultCellStyle.NullValue = null;

I guess I jumped the gun asking here, but hope this helps someone else sometime.

Sign up to request clarification or add additional context in comments.

9 Comments

How can I do the same in VB.NET? = Nothing I suppose?
I was looking for the same. Based on your idea, I just changed it in the Form.Designer.cs (of course, woks only if the datagridview is not dynamically generated)
As I indicated below, it's a lot easier/simpler and safer to simply assign new BitMap(1,1) to the cell's Value property. Trying to assign NULL as described above is a hit and miss proposition that can be a major pain to make work, if you ever even manage to.
@NetXpert - I'm failing to see how it's easier or simpler - it looks to be about exactly as easy and exactly as simple. You haven't explained anything about why you think the original answer is "hit and miss" or what problem you had with it. There's always multiple ways to solve a problem, and your way apparently works so kudos on figuring that out, but as far as I know, there is no problem whatsoever with the original approach above of using .NullValue, unless you care to elaborate on the problems you encountered with it.
I didn't say that your solution doesn't work, I'm sure that it does, at least in some, (heck, given the reception, probably even most) circumstances. What I am saying though, is that it doesn't work in all circumstances and is both more complex and less intuitive than simply always just assigning some kind of actual value to the cell and getting the expected result. I didn't say your solution isn't a solution, I just said that it's an inferior one, for the reasons already stated.
|
7

It's FAR easier to simply assign new Bitmap(1,1); to the cell's .Value property and move on. My app was throwing exceptions whenever I tried to assign NULL to the Cell's Value, even with the modified DefaultCellStyle.NullValue

Something like this works as intended, every time, without any hassles or arcane/obscure settings:

dataGridView1.Rows[index].Cells["CellName"].Value = isFlag ? Properties.Resources.FlagImage : new Bitmap(1,1);

2 Comments

It apparently bears mentioning, that, in a DataGridView with large numbers of cells that could require this assignment, it's preferable to create a single Bitmap instance and assign that each time, rather than creating possibly thousands of individual Bitmap() objects to effect the same net result.
it is not working if you defined the column via designer :(
3

To fix whole grid, just add this code to Form constructor. (and change name of your dataGrid):

        Load += delegate
        {
            // remove default [x] image for data DataGridViewImageColumn columns
            foreach (var column in dataGridView1.Columns)
            {
                if (column is DataGridViewImageColumn)
                    (column as DataGridViewImageColumn).DefaultCellStyle.NullValue = null;
            }
        };

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.