How to remove empty row from gridview - c#

I have a problem in window application. When I insert a record and display the records in a gridview, the gridview automatically makes one empty row. And I also use
dataGridView1.AllowUserToAddRows = false;
Please help me with an alternative solution to get rid of the empty row.

Default DGV will have a blank row at the bottom to enable user adding a new row, by setting dataGridView1.AllowUserToAddRows = false; will disable the blank row.
You may delete the blank rows manually like this:
for (int i = 1; i < dataGridView1.RowCount - 1; i++)
{
Boolean isEmpty = true;
for(int j=0;j<dataGridView1.Columns.Count; j++)
{
if (dataGridView1.Rows[i].Cells[j].Value.ToString() != "" )
{
isEmpty = false;
break;
}
}
if (isEmpty)
{
dataGridView1.Rows.RemoveAt(i);
i--;
}
}
HTH.

Are you sure you don't have a blank record in your datasource? another way you could check this is to add an if statment on to the OnRowDataBound to check the item index which if 0 (or some other way to identify the blank row) then set the row's Visible = false

Related

clear datagridview duplicate rows and keep unique rows

so when filling my datagridview I normally do something like
public void FillTable(CoBRAMetaField[] metaFields)
{
dataGridView.Rows.Clear();
// do something with metaFields
}
Important:
CoBRAMetaField is a object with a ID and other stuff
Each row in the grid holds a metafield object
My grid gets filled correctly (sorry, the language is german)
When I fill the grid another time I only want to remove the rows with metaFields that don't exist in the new metaFields array. I want this behaviour because when a user selected a value for this row I don't want it to get removed and created again because then the selected value is removed too.
I came up with this
public void FillTable(CoBRAMetaField[] metaFields)
{
for (int i = 0; i < dataGridView.Rows.Count; i++) // loop through the grid rows
{
double metaFieldID = (dataGridView.Rows[i].Cells[0].Tag as CoBRAMetaField).ID; // get the ID from the row metaField
if (metaFields.Any(field => field.ID == metaFieldID)) // Does it exist?
metaFields = metaFields.Where(field => field.ID != metaFieldID).ToArray(); // Remove it from the new array
else // it doesn't exist
dataGridView.Rows.Remove(dataGridView.Rows[i]); // remove the row
}
// Fill the grid with the remaining metaFields
}
The first run gets initialized correctly
the second run seems to crash, some fields remain empty
when I press the button on this row I get a nullpointer exception. I only get this error when using the "new code" so am I missing something? Is there something I didn't think about?
I will provide a full example here
At first create a DataGridView and Button on the form. Create a file for all required classes and take this snippet
https://pastebin.com/BFmr2ps9
After that fill the forms code with some test data
https://pastebin.com/Yz84Akkj
and now setup the DataGridView logic
https://pastebin.com/qH6kZKZv
I added
dataGridView.AllowDrop = false;
dataGridView.AllowUserToAddRows = false;
dataGridView.AllowUserToDeleteRows = false;
dataGridView.AllowUserToOrderColumns = false;
dataGridView.AllowUserToResizeRows = false;
if you just want to copy paste but you can also do it by the forms designer. Have a look at dataGridView.Rows.Clear(); this provides a working example. Comment it out and use the code above to test the incorrect example
The main problem is in the code for adding rows (taken from the link):
// Fill the grid with the remaining metaFields
for (int i = 0; i < metaFields.Length; i++)
{
MetaField currentMetaField = metaFields[i];
dataGridView.Rows.Add(currentMetaField.Name, null);
DataGridViewRow newRow = dataGridView.Rows[i]; // <-- Problem!
DataGridViewCell metaFieldCell = newRow.Cells[0];
metaFieldCell.Tag = currentMetaField;
(newRow.Cells[1] as DataGridViewAllocationCell).Initialize(releaseSetupData);
}
In the marked line you are assuming that the index of the added row is the same as i, which is true when you start with empty grid, bit not when the grid is updated and some old records are kept.
The proper way of handling it is to not assume the new row index - it is returned by the Add method:
int rowIndex = dataGridView.Rows.Add(currentMetaField.Name, null);
DataGridViewRow newRow = dataGridView.Rows[rowIndex];
This will solve the original issue from the question.
There is also a problem in the remove part of the code - the for loop will miss checking the rows next to the removed ones. Anytime you want to iterate some list and remove items during the iteration, use reverse for loop and RemoveAt:
for (int i = dataGridView.Rows.Count - 1; i >= 0; i--) // <--
{
double metaFieldID = (dataGridView.Rows[i].Cells[0].Tag as MetaField).ID;
if (metaFields.Any(field => field.ID == metaFieldID))
metaFields = metaFields.Where(field => field.ID != metaFieldID).ToArray();
else
dataGridView.Rows.RemoveAt(i); // <--
}
The removal code could further be improved (currently looks inefficient with these Any, Where + ToArray), but at least with the above changes it will work correctly.

Bind and Highlight Specific DataGridView Row

I am binding data from excel file in a list on button click and this works perfectly. Finally the data is binded to a DataGridView. Now I want to iterate the list to check if there are any data that isn't included to the database after binding to a DataGridView. If any data mismatches, then it should highlight the specific row with red color in the DataGridView. Note: There could be multiple data that will not match. Something as the below image and the code tried:
grdUpload.Rows.Clear();
for (int i = 0; i < lstData.Count; i++) //lstData - The Data List
{
if (Facede.ExcelUpload.CheckIfExists(lstData)) //Checking if any data mismatches
{
grdUpload.DataSource = lstData;
grdUpload.Rows[i].DefaultCellStyle.BackColor = Color.Red; //Highlight the row data that mismatches
}
else
{
grdUpload.DataSource = lstData;
}
}
public bool CheckIfExists(List<Data> lst)
{
bool flag = false;
foreach (Data d in lst)
{
string Query = "SELECT M.EmpNo FROM Data m WHERE M.EmpNo = '" + d.EmpNo + "'";
DataTable dt = SelectData(Query);
if (dt != null && dt.Rows.Count > 0)
{
flag = true;
}
else
{
flag = false;
}
}
return flag;
}
Now the issue is it doesn't highlight the specific row if data like EmpNo mismatches. Anything that I am missing here?
Problem is in your for loop.
You are firstly binding data to your datagridview.
Then you are entering for loop
Inside it you ask if condition is met and if it is you AGAIN bind same data to datagridview but after it you color it.
For loop continues and it again enters part where it meets condition and AGAIN you BIND same data but now you overwrite colored data with new (but same) data and then color some new row.
So what you need to do is
Load data into datagridview
Loop through datagridviewrows and if meet condition color that row
So code should look like this:
//Here you bind your data to datagridview
//In code bellow if you want to get row's column's data use
//row.Cells["CELL_VALUE"].Value (convert to what datatype you need before comparing)
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (condition)))
{
dataGridView1.Rows[row.Index].DefaultCellStyle.BackColor = Color.Red;
}
}

Is there a quick way to set all columns of DataGridView invisible?

I don't want to loop through all the columns and set each column's Visible to false. I wonder if there is a quick way to do so.
Thank you!
Also you can use LINQ as below:
dataGridView1.Columns.OfType<DataGridViewColumn>().ToList().ForEach(col => col.Visible = false);
dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
dataGridView.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;
for (int i = 0; i < dataGridView.Columns.Count; i++)
{
dataGridView.Columns[i].Visible = false;
}
set data source to null, when you want to show it again, you can set the data source back.
Or you can set Gridview visible false or gridview containing control to visible false.
Have two grids the same exact size and location.
if(conditionMet)
{
grid1.visible = false;
grid2.visible = true;
}
Old Question thought it might be helpful for someone !! This might be an easy option..
foreach (DataGridViewColumn col in myDgv.Columns)
{
col.Visible = false;
}
as well as you can iterate through rows..
foreach (DataGridViewRow row in myDgv.Rows)
{
// your code
}

Remove link text in Datagridview

I have a DataGridView which is populated from a list. I then Have defined a link column in the last column which is not DataBound saying View, how do I remove this link text if a condition is met. I have the below:
dgvReport.AutoGenerateColumns = false;
dgvReport.DataSource = queries;
//locals
Int32 lastColumnIndex = this.dgvReport.Columns.Count - 1;
//hide reads links for the null queries
for (int i=0; i < queries.Count; i++) {
if (queries[i].SomeID == null || queries[i].AnotherID == null) {
this.dgvReport.Rows[i].Cells[lastColumnIndex].Value = "";
}
}
This is not working and my column text still shows View. Any ideas?
Edit: lastColumnIndex is 24 which is indeed the last column index
You might try
View.PlainTextBehaviour = true;
It will remove the link and show it as plain text

How to restrict datagridview to create 2 rows?

I've datagridview in my windows application. By default the datagridview loads with 1 row. If we type something in the cell it creates another row below this row. It goes on like this. Now if someone types something and then deletes it, the row created below doesn't get deleted. I want to stop user from creating unlimited no. of rows without any data. Is it possible to restrict the datagridview to create maximum 2 such blank rows? Please suggest, how it can be done.
It cannot be achieved automatically. You will need to do that manually. The best way to that is properly handling of cellvalidating and cellvalidated event. And cancel event if cells are empty. You can also set property AllowUserToAddRows=false and manually add new row e.g. by pressing button:
// source is IBindingSource
MyObject newObject = this.source.AddNew();
DataGridViewRow row = this.dgv.Rows[this.source.IndexOf(newObject)];
row.Selected = true;
int maxSelectedOrder = this.source.IndexOf(newObject );
int minSelectedOrder = this.source.IndexOf(newObject );
int displayedRows = this.dgv.Rows.GetRowCount(DataGridViewElementStates.Displayed);
int firstDisplayed = this.dgv.FirstDisplayedScrollingRowIndex;
int lastDisplayed = displayedRows + firstDisplayed - 1;
if (maxSelectedOrder - 1 > lastDisplayed && minSelectedOrder - 1 > firstDisplayed)
{
int firstToDisplay = displayedRows + firstDisplayed - 1 - (displayedRows - 1);
if (firstToDisplay > 0)
{
this.dgv.FirstDisplayedScrollingRowIndex = firstToDisplay;
}
}
this.dgv.CurrentCell = row.Cells[0];
this.dgv.Focus();
Set the property AllowUserTAddRows=false; or through code
myDataGridView.AllowUserToAddRows = false;

Categories

Resources