Make null columns invisible in DataGridView - c#

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.
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;
}
}

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

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

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

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.

Related

How to create a method where multiple controls are false in an "if" statement for C#?

What is the best way to simplify this (via method creation or otherwise):
if ((radioButton1.Checked == false) && (radioButton2.Checked == false) && (radioButton1.Checked == false) && ...more similar controls... && ((radioButton99.Checked == false))
{
MessageBox.Show("Please select an option!);
}
Thank you for your consideration. Apologies for any inconvenience or grievances caused.
You could put all those controls in a List and then check whether any of the controls in the list is checked. This can be done in several ways. Below examples of two of those.
Example using loop:
bool optionSelected = false;
foreach(var control in controls) // the List is in this case called controls
{
if(control.Checked)
{
optionSelected = true;
}
}
// Check the boolean
Example using System.Linq:
if(!controls.Any(c => c.Checked))
{
MessageBox.Show("Please select an option!);
}
You need to add your controls into a public collection to simply iterate them.
if you have a bunch of the same type controls, it's better to put them into a array in your form's constructor :
CheckBox[] MyBoxes = new CheckBox[]{ check01, check02 , ... }
// MyBoxes is filled at Form_Load and it's usable in throughout of the form
bool result = true;
for(int i=0; i<MyBoxes.Length; i++)
{
if (MyBoxes[i].Checked == false)
{ result = false; break; }
}
another solution is to iterate whole controls on the form:
bool result = true;
for(int i=0; i<this.Controls.Count; i++)
{
if (this.Controls[i] is CheckBox)
{
if ((this.Controls[i] as CheckBox).Checked == false)
{ result = false; break; }
}
}
If you have lots of controls (in this case - RadioButtons), then you can use the following trick - Tag property.
To summarize:
1) Set Tag property with the some string to differentiate from other controls (in particular, there may be the case when not all the controls of one type must be processed).
2) Collect these controls with defined string in Tag and process them.
In your particular case, you can set the string ToCheck in Tag and then check whether all RadioButtons are checked:
// Collect controls with defined string in Tag property
var radioButtons = this.Controls
.OfType<RadioButton>() //Filter controls by type
.Where(rb => ((string)rb.Tag) == "ToCheck"); //Get controls with defined string in Tag
// Check whether all RadioButtons are checked
bool allChecked = radioButtons.All(rb => rb.Checked);
The possible approach could be to introduce variable for condition validation
bool optionIsSelected = ((radioButton1.Checked == true) || (radioButton2.Checked == true)...;
And then use it in if:
if (!optionIsSelected)
{
MessageBox.Show("Please select an option!);
}
private bool AreAllFalse(params bool[] thingsToCheck)
{
return things.All(t => !t);
}
Usage
if (AreAllFalse(radioButton1.Checked,radiobutton2.Checked, etc)
{
//Do what you want
}
The benefit of using the params key word is that it creates the array for you when you call the method. It also allows you to pass in just one thing to check if you want. While that would be quite pointless here, it just keeps things felxible and is something worthwhile knowing

Checking for empty string before inserting the record

I am custom importing some rows from a text file to our database and so I have bunch of codes like this for many fields.
address.State = row["Location State"].ToString();
I just noticed a requirement that says
don't overwrite those fields in the value that we are reading from the
text file is empty or blank.
So I assume I can wrap them all around a check like this?
if(!String.IsNullOrEmpth(row["Location State"].ToString()))
address.State = row["Location State"].ToString();
But before I go ahead and apply this kind of logic around all those fields I wanted to check and see if you have better solutions?
Maybe an extension method could help here:
public static string ColumnValueOrDefault(this DataRow row, string column, string defaultValue)
{
if (row == null)
{
throw new ArgumentNullException("row");
}
if (column == null)
{
throw new ArgumentNullException("column");
}
if (defaultValue == null)
{
throw new ArgumentNullException("defaultValue");
}
var rowString = row[column].ToString();
return string.IsNullOrEmpty(rowString) ? defaultValue : rowString;
}
Address.State = row.ColumnValueOrDefault("column", Address.State);
I would (and do) use this pattern personally :
string sTester = string.Empty
Address.State = string.IsNullOrEmpty(sTester = row["collumn"].ToString()) == false ? sTester : Address.State;
This allows each collumn value to be set once, and the reused using the same string variable, and is relatively readable

How to make a checkbox disabled without using any specific condition?

I have a checkbox whose value is handled from the DB on the basis of the column isAllow. We have 5 names and corresponding to these name we have diff isAllow property. If the value of isAllow is true then the checkbox get checked.
For four names, I have to make the checkbox as checked, but for one specific name out of 5, I have to mark the checkbox as disabled as well. I can achieve this by adding a condition as:
if(name=="Josh" && isAllow)
{
chkBrand.Enable=false;
chkBrand.Checked=true;
}
I dont want to use the above condition here. I just want to get the checkbox as disable for a specific name without the condition.
Below is the code that I have used:
bool isAllow = false;
bool SigCard = false;
List<AOTLuAffinity> oAotluAffinity = bsAffinity.DataSource as List<AOTLuAffinity>;
foreach (AOTLuAffinity oAffinity in oAotluAffinity)
{
if (oAffinity.Name == comboName.SelectedValue.ToString())
{
isAllow = oAffinity.isAllowName;
signCard = AOTHelper.GetHasSigCardValue(workflowid, Acct.AffinityNum, comboPaBranch.SelectedValue.ToString(), Applicants.AffinityNum, isSignCard, isAllow );
if (isAllow)
{
chkBrand.Checked=true;// here for a specific name, I want to make the checkbox as disabled, but I dont want to use the condition.
}
else
{
chkBrand.Checked=false;
}
break;
}
}
I am finding a hard time in getting this. Any help will be great.
I think the right approach here is to add a new field to the database, isDisabled, and then in your loop evaluate that field:
...
else
{
chkBrand.Checked=false;
}
if (oAffinity.isDisabled)
{
chkBrand.Enabled = false;
}
break;
You can use LINQ conditions to check specific names on a list. You must declare a list like this:
List<Person> peopleList = new List<Person>();
And here is your condition code:
foreach (AOTLuAffinity oAffinity in oAotluAffinity)
{
if (oAffinity.Name == comboName.SelectedValue.ToString())
{
isAllow = oAffinity.isAllowName;
signCard = AOTHelper.GetHasSigCardValue(workflowid, Acct.AffinityNum, comboPaBranch.SelectedValue.ToString(), Applicants.AffinityNum, isSignCard, isAllow );
chkBrand.Checked =
peopleList
.Count(c => c.Name == comboName.SelectedValue.ToString()) > 0 ? true : false;
break;
}
}
Loop on the items you got from database and each time read value (isAllow),then
chkBrand.Checked=isAllow;

linq check if matches null or selected item

I am checking to see if items already match whats in my MSSQL DB. I am using LINQ to update records. I would like to know how i can check if an item is equal to d_0_2 or if its equal to null/empty. How would i go about doing this?
below is my existing code, which partially works. but is failing due to the null/Empty
if (updateProduct.studioId == Convert.ToInt32(d_0_2.SelectedValue)) { }
else { updateProduct.studioId = Convert.ToInt32(d_0_2.SelectedValue);}
Thanks in advance.
I'm not sure if I understood you question correctly, but you want to check if item is null or if not is it studioId equal to d_0_2.SelectedValue
if (updateProduct == null)
{
//create new update product
}
else if (updateProduct.studioId != Convert.ToInt32(d_0_2.SelectedValue))
{
updateProduct.studioId = Convert.ToInt32(d_0_2.SelectedValue);
}
string value = d_0_2.SelectedValue.ToString();
// what if SelectedValue is empty or null?
if (!string.IsNullOrEmpty(value))
return;
// what if product is null?
if (updateProduct != null)
return;
if (updateProduct.studioId != null &&
updateProduct.studioId == Convert.ToInt32(value))
{
// you have product and its id equal to d_0_2.SelectedValue
}
else
{
// studioId not equal to to d_0_2.SelectedValue
updateProduct.studioId = Convert.ToInt32(value);
}

export null values to xml from a dataset

If you have a null value in a field in a dataset and export it to xml it does "remove" the field tag .. anyway to avoid this..
An empty tag does not have the same meaning as null, especially for strings. How would you make the difference if the tag was present but empty?
//Try changing values of cells.
foreach (DataRow row in dtPr.Rows)
{
for (int i = 0; i < dtPr.Columns.Count; i++)
{
dtPr.Columns[i].ReadOnly = false;
if (string.IsNullOrEmpty(row[i].ToString()))
{
if (dtPr.Columns[i].DataType == typeof(string))
row[i] = string.Empty;
else if (dtPr.Columns[i].DataType == typeof(int))
row[i] = 0;
else if (dtPr.Columns[i].DataType == typeof(DateTime))
row[i] = new DateTime(1753, 1, 1);
}
}
}
Think of NULL as a state and everything else as a value. So if you want a blank value, just send in an empty string (single white space)
you have to paint your method with an attribute that tells it to stay there. not near my winblows machine so cant give you the actual code. but would look something like this,
[XMLElement(IsNullable = true)]
myProperty {get;set;}

Categories

Resources