How to disable Null image in DataGridView image column when populated from DataTable

27,674

Solution 1

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.

Solution 2

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);

Solution 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;
            }
        };
Share:
27,674
Jim
Author by

Jim

Updated on June 26, 2020

Comments

  • Jim
    Jim almost 4 years

    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.

  • usamazf
    usamazf about 8 years
    How can I do the same in VB.NET? = Nothing I suppose?
  • Antoine
    Antoine about 6 years
    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)
  • NetXpert
    NetXpert about 4 years
    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.
  • Jim
    Jim about 4 years
    @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.
  • NetXpert
    NetXpert about 4 years
    @Jim 1) I tried to make the above "solution" work (for hours) and never succeeded. 2) Re-casting to another type, to set a separate parameter, to allow assignment of NULL to make a graphic cell empty is the antithesis of simple and straightforward. 3) Assigning a graphic element to the cell in all circumstances is easier to read and intuitively understand what's being done. 4) If one solution is more straightforward/intuitive, doesn't require any casting/parameter changes and doesn't throw exceptions, it's reasonable to describe that as being "simpler and easier" to the alternative.
  • Jim
    Jim about 4 years
    @NetXpert Your experience isn't representitive of mine, or likely anyone else's. The solution above works fine, and I'd challenge you to show evidence otherwise. Your solution involves creating new objects for each column, which is both less efficient and not as intuitive, though I will concede that those things likely don't matter for most implementations. The point being, these are two separate ways to go about the same thing. I can't say why you personally had problems implementing it this way, but I can tell you it does work with very little effort else 30 ppl wouldn't have upvoted it
  • Jim
    Jim about 4 years
    @NetXpert, I'd respectfully ask you to post an application that demonstrates how the above approach throws some kind of exception, and we shall see whether the problem is with the approach or if it's between the keyboard and chair. I'd suspect the latter, and you've shown no evidence otherwise other than vague descriptions of "endless exceptions". If you believe the above doesn't work, then demonstrate it - that shouldn't be too hard to do.
  • NetXpert
    NetXpert about 4 years
    To explain why I'm not going to try and recreate the issue now: the problem appeared when we tried to implement a diagnostic Form with a dynamically-generated DGV to show the contents of objects that were based on classes dynamically configured using custom XML data loaded on the fly via an internal web API. There was a LOT going on underneath the DGV! The only problem we encountered though, were exceptions every time we tried to assign NULL to a cell's ```Value`` property via your "solution". MY solution finally resolved the problem entirely and everything worked as expected thereafter.
  • NetXpert
    NetXpert about 4 years
    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.
  • NetXpert
    NetXpert about 3 years
    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.
  • Yesyoor
    Yesyoor almost 3 years
    it is not working if you defined the column via designer :(