Display Datagridview dynamically created chechboxvalue? c# - c#

I want to check all/ only certain Checkboxes as checked.
I tried various versions from stackoverflow but none seem to work out.
The code is called directly after dynamically creating the datagrid as I only want to load the Data once. - Datagrid is created in my Form_Load
The value of the Checkboxes are changed but not displayed.
//This is how i create the Datagrid column - not question relevant
for (int kacnt = 1; kacnt <= Ei.Kaanzahl; kacnt++)
{
DataGridViewCheckBoxColumn Kachk = new DataGridViewCheckBoxColumn();
Kachk.HeaderText = "Kamera" + kacnt;
Kachk.Width = 70;
WarDataGridView.Columns.Add(Kachk);
}
// The code I actually have problems with - the display of the value
foreach (DataGridViewRow row in WarDataGridView.Rows)
{
for (int col = 1; col < WarDataGridView.ColumnCount; col++)
{
(WarDataGridView.Rows[row.Index].Cells[col] as DataGridViewCheckBoxCell).Value = true;}}

Set your columns' True and False values like so:
Kamerachk.TrueValue = true;
and
Kamerachk.TrueValue = 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;
}
}

DataGridComboBoxColumn Values Different For each Row

I am trying to populate a datagridview combobox column with comboboxcells in winforms where each row has a different collection derived from the nested list within the dictionary, the dictionary works fine when i iterate over it and get its objects and their string values, however every different combination i have exhausted to populate the combobox cells on form load has failed. Is it possible? I have found other posts where they use cellclick events etc. I prefer to populate on form initialization.
//this works
public void create datatable()
{
DataGridViewComboBoxColumn Data_CmBx_Col_ObjectType = new DataGridViewComboBoxColumn();
Data_CmBx_Col_FamilyType.Name = _ADD_OBJECT_TYPE;
Data_CmBx_Col_FamilyType.HeaderText = _ADD_OBJECT_TYPE;
dataGridView.Columns.Insert(6, Data_CmBx_Col_ObjectType);
//pop combobox, the dictionary works
int i = 0;
foreach (KeyValuePair<object, List<objectType>> objectAndType in combined_Dictionary)
{
i++;
if (rowIndex <= combined_Dictionary.Count)
{
CreateCustomComboBoxDataSouce(i, objectAndType.Value);
}
}
//Bind dataGridView to a datatable
dataGridView_Family.DataSource = data;
}//end method
//method is called and fails with index out of range error collection
private void CreateCustomComboBoxDataSouce(int row, List<objectAndType> type) //row index ,and two parameters
{
DataGridViewComboBoxCell comboCell = dataGridView_objectAndType[6, row] as DataGridViewComboBoxCell;
comboCell.DataSource = new BindingSource(type, null);
}//end method
The index is zero based, so it must be strictly less than its count
if (rowIndex < combined_Dictionary.Count) // not <= but without =

c# : How ot create a grid row array programatically

I am working in c# and i am under a situation where i have a grid (childGrid) and inside this grid i want to create 3 more grids dynamically.
I want to achieve it using arrays. My try to do this is:
Grid[] row = new Grid[counts]; //counts=3 in my case but decde dynamically.
for (int i = 0; i < counts; i++)
{
row[i].RowDefinitions.Add(new RowDefinition());
}
I do so because i have one childGrid (parent grid) on that i will have 3 containers (3 more grid as container as child of chidGrid) so it is row[i] in my case (for i :0 to <3) (if you see the code). and on row[0]. i have a checkbox and two different UIelements at row[1 & 2] . I take different containers because if i select the check of row[0](checkbox) it will set the opacity of row[1].opacity=0.5; and on unchecking it will do row[2].opacity=0.5;. So thats why i have different 3 grids container on a grid.
the line row[i].RowDefinitions.Add(new RowDefinition()); gives warning.
The object reference is not set to an instance of an object.
How to achieve this ? I can not do statically because i dont know statically the value of counts(which i assumed 3 here)
You didn't actually create any grids before you tried to add rows to them.
Grid[] row = new Grid[counts];
for (int i = 0; i < counts; i++)
{
row[i] = new Grid();
row[i].RowDefinitions.Add(new RowDefinition());
}
If I interpret your question correctly, the proper way to set all the rows to a default value is not to add them, but to set them.
for (int i = 0; i < counts; i++)
{
row[i].RowDefinitions[counts] = new RowDefinition();
}

Trying to transfer from one dataGridView to another accordingly

My datagridView1 contains 7 columns, and first one has dates.
I'm trying to transfer january data from dataGridView1 to dataGridView2
I did try using a loop, which logically thought it would work, but it would give me nullExceptions
Here's my code:
for (int i = 0; i < f1.dataGrivView1.Rows.Count; i++)
{
if (f1.dataGrivView1.Rows[i].Cells[0].Value.ToString().Split('/')[1].StartsWith("01"))//if january..
{
dataGrivView1.Rows.Add();//datagridview in current form
dataGrivView1.Rows[i].Cells[0].Value = f1.dataGrivView1.Rows[i].Cells[0].Value.ToString();
dataGrivView1.Rows[i].Cells[1].Value = f1.dataGrivView1.Rows[i].Cells[1].Value.ToString();
}}
And after some googling, I saw you can't just copy data this way and you need to clone it, so I tried.
foreach (DataGridViewRow dgvr in f1.dataGridView1.Rows)
{
DataGridViewRow r = dgvr.Clone() as DataGridViewRow;
foreach (DataGridViewCell cell in dgvr.Cells)
{
if (cell.Value.ToString().Contains("/01/"));
r.Cells[cell.ColumnIndex].Value = cell.Value;
}
dataGridView1.Rows.Add(r);
}
But.. same thing.
Any idea?
This does indeed copy the first column values from a DataGridView to another.
for(int i=0; i<f1.dataGridView1.Rows.Count; i++)
dataGridView1.Rows[i].Cells[0].Value = f1.dataGridView1.Rows[i].Cells[0].Value;
Any exceptions thrown are probably due to the new dataGridView1 not having the existing rows at the corresponding index in the iteration.

Categories

Resources