1

I have a datagridview in WinForm C# application called custFleetDataGrid

I've tried to create a method which will set each column to invisible if all the rows are null or ""

The code does not work as expected, columns with blank data remain in the grid view.

Blank Rows

I'm calling Code like this

custFleetDataGrid.RemoveEmptyColumns();

Method I'm using to remove NullColumns

public static class ExtensionGridView
{
    public static DataGridView RemoveEmptyColumns(this DataGridView grdView)
    {
        foreach (DataGridViewColumn clm in grdView.Columns)
        {
            bool notAvailable = true;

            foreach (DataGridViewRow row in grdView.Rows)
            {

                if (row.Cells[clm.Index].Value == null || row.Cells[clm.Index].Value.ToString() != "")
                {
                    notAvailable = false;
                    break;
                }
            }

            if (notAvailable)
            {
                grdView.Columns[clm.Index].Visible = false;
            }
        }

        return grdView;
    }
}
Brendan Gooden
  • 1,460
  • 2
  • 21
  • 40
  • Possible duplicate of [What is a NullReferenceException, and how do I fix it?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – ASh Jun 15 '16 at 06:49
  • @Brendon You are trying to obtain the `Value` of an empty `Cell`.So check if `Cell` is null then try to get the `Value` – Chaitanya Jun 15 '16 at 06:52
  • OK so... how do i fix? – Brendan Gooden Jun 15 '16 at 06:52
  • @Chaitanya The `Value` is `null`, not the `Cell` itself. Check my answer. Therefore the `.ToString()` is causing the exception. – C4d Jun 15 '16 at 06:57

4 Answers4

1

If Value is null, you'll get a NullReferenceException if using ToString() on it. So you have to null-check the value before using ToString().

Go like this:

// IF (Value is empty => use "").ToString() <-- IsNullOrEmpty
if (!string.IsNullOrEmpty(row.Cells[clm.Index].Value ?? "").ToString())
{
    notAvailable = false;
    break;
}

Check the details about ?? here.

Its the same as:

// If not null
if(row.Cells[clm.Index].Value != null)
{
    // If string of value is empty
    if(row.Cells[clm.Index].Value.ToString() != "")
    {
        notAvailable = false;
        break;
    }
}

Away from your problem here's a short version of everything:

public static DataGridView RemoveEmptyColumns(this DataGridView grdView)
{
    for (int i = 0; i < grdView.ColumnCount; i++)
    {
        // On each iteration get all values of a column
        IEnumerable<string> column = grdView.Rows.Cast<DataGridViewRow>().Select(row => (string)row.Cells[i].Value);
        // If there is no value with length > 0 => visible = false
        if (!column.Any(x => x.Length > 0)) { grdView.Columns[i].Visible = false; }
    }

    return grdView;
}
Community
  • 1
  • 1
C4d
  • 3,183
  • 4
  • 29
  • 50
1

could this be because the compiler is trying to convert a null value to a string?

Correct, that's the exact case. Just it's not the compiler, but the code you have written.

I would suggest you encapsulating the empty cell logic into separate extension method inside the ExtensionGridView class:

public static bool IsEmpty(this DataGridViewCell cell)
{
    var value = cell.Value;
    return value == null || value == DBNull.Value || (value as string) == string.Empty;
}

Then you can use simple LINQ to determine the empty columns:

public static IEnumerable<DataGridViewColumn> EmptyColumns(this DataGridView gridView)
{
    return gridView.Columns.Cast<DataGridViewColumn>()
        .Where(c => gridView.Rows.Cast<DataGridViewRow>().All(r => r.Cells[c.Index].IsEmpty()));
}

Then your method could be simply like this:

public static DataGridView RemoveEmptyColumns(this DataGridView gridView)
{
    foreach (var column in gridView.EmptyColumns())
        column.Visible = false;
    return gridView;
}
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • It will, if you put all these methods inside the `ExtensionGridView` class as mentioned in the post. – Ivan Stoev Jun 15 '16 at 09:23
  • You forgot to copy the `public static bool IsEmpty(this DataGridViewCell cell)` method from the answer. – Ivan Stoev Jun 15 '16 at 09:28
  • Also, the code seems to be deleting some columns that are not empty? Here is before https://www.dropbox.com/s/26a8q7giqea3iir/Before.JPG?dl=0 And here is after https://www.dropbox.com/s/4z018ii2zpmgdcd/After.JPG?dl=0 – Brendan Gooden Jun 15 '16 at 11:15
  • That's weird. Trying to reproduce, but can't. Can you put a breakpoint at `column.Visible = false;` line and see if it is called for wrong columns. – Ivan Stoev Jun 15 '16 at 11:47
  • Yep it is calling for the wrong column! Any ideas?? – Brendan Gooden Jun 16 '16 at 00:48
  • Managed to get it to work if i added a 'ShowAllColumns' function before the 'Hide' function. Thanks! – Brendan Gooden Jun 16 '16 at 03:58
0

Instead of iterating trough each row i'd let my select statement do it like so: SELECT some columns FROM yourtable WHERE thecolumn IS NOT NULL

Dwight
  • 673
  • 7
  • 15
  • Then it will not get the row at all. He needs to make the column invisible if all the rows have no data for that column. So if no user have data on the surname column, the surname column will be invisible. With your query no data would be selected – Aimnox Jun 15 '16 at 06:59
  • Maybe i misunderstood the question, i was thinking that he dint want a empty column ? the query would only select columns where at least one row has data. – Dwight Jun 15 '16 at 07:33
0

Your problem is that you are checking if row.value.toString() is null or empty. If valueis null, when it tries to get the toString() to check if its null or empty it can't.

Change your if statement to:

if (row.Cells[clm.Index].Value != null || row.Cells[clm.Index].Value.toString()!="")
{
    //Code
}

Important note:

In C# (and most modern languages) you have two opetaors for OR (| and ||) and two for AND(& &&). If its just one (&/|) it will check both sides but if it have two (&&/||) if the first condetin determines eveirthing (a true for OR or a false for AND) it will not check the second one.

This gives you more rendiment but also is usefull for not having nullpointerexeptions. If it's null, it will not check the second part and it will not explote. If you just put one it will say "Yes, is null, lets check if the string is also "" and will throw a NulPointerExeption.

Aimnox
  • 895
  • 7
  • 20
  • He is checking for `Not` being null. Change it to `!= null`. – C4d Jun 15 '16 at 07:26
  • This wont work anyway. If `Value == null` it will jump to the second condition and raise the `NullReferenceException` again as `toString()` cant be called on a `null` value. – C4d Jun 16 '16 at 08:26