This is the table. On the right are the namesI have a gridview that shows a table from the database. I want to search a name in the gridview using a textbox and a button. This is what i have so far. When i want to search I get in a messagebox this: object reference is not set on an instance of an object.
private void btn_zoek_Click(object sender, EventArgs e)
{
string searchValue = tb_SearchOverzicht.Text;
metroGrid1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
try
{
foreach (DataGridViewRow row in metroGrid1.Rows)
{
if (row.Cells[2].Value.ToString().Equals(searchValue))
{
row.Selected = true;
break;
}
}
}
catch (Exception exc)
{
MessageBox.Show(exc.Message);
}
}
Check if the values and object you are trying to work with are filled with data and not null.
In your row
if (row.Cells[2].Value.ToString().Equals(searchValue))
you should check first, if the cell exists and has value, like this:
if(row.Cells[2] != null && row.Cells[2].Value.ToString() == searchValue)
{
// Some code
}
and just to be sure, check if your searchValue is not empty or without any chars or maybe even correct formatted:
if(!String.IsNullOrWhiteSpace(searchValue))
but I dont think this is necessary here, just nice to have.
The goal here is: Not all values have to be filled. It can appear that a cell doesnt have value in that column, the row may be the filter row or even empty, or worst: the grid isn't even initialized. So please try to check if values or objects are filled before using them.
Related
i know this question maybe a duplicate of others, but i'm losing my mind trying to understand what's going on.
This program of mine loads a list of excel files, and when one of them i selected, i can choose which sheet i want to display with the datagridview.
Now, having data_ListDisplay as DatagridView populated with 211 rows:
With the code below, i would like to find the colum.index of the first cell in row collection in datagridview which has the given "string" that matches with the search criteria.
However, the row.count is ALWAYS = 0.
Yesterday it was working fine (OFC it was..). Then, i needed to make the datagridview PUBLIC to use the data inside to populate another list (data is elaborate while populating) which belongs to another class.
Code is fine, no error and the line i used to make data_listDisplay puplic is
public DataGridView DataGridCR { get { return data_ListDisplay; } }
Hereafter the piece of code (in the original code, the 2 foreach construct belongs to 2 private methods that calculates the variables CrAnalysedCol and CrRealisedCol. I put them in the same method to be fast in copy/paste here)
private void cbo_List_SelectedIndexChanged(object sender, EventArgs e)
{
//Fill data_ListDisplay with the data set (datagridview) by changing the combobox value
dt = tablecollection[this.cbo_List.SelectedItem.ToString()];
data_ListDisplay.DataSource = dt;
label3.Text = ($"Column Count{data_ListDisplay.Columns.Count}/Row Count {data_ListDisplay.Rows.Count}"); //Debug Purpose
foreach (DataGridViewRow row in data_ListDisplay.Rows)
{
foreach (DataGridViewCell cell in row.Cells)
{
if (cell.Value.ToString().Contains("CR to validate"))
{
CrRealisedCol = cell.ColumnIndex;
}
}
}
foreach (DataGridViewRow row in data_ListDisplay.Rows)
{
foreach (DataGridViewCell cell in row.Cells)
{
if (cell.Value.ToString().Contains("CR analysed"))
{
CrAnalysedCol = cell.ColumnIndex;
}
}
}
}
where:
cbo_List is a combobox which is filled with all sheets in the workbook selected and both CrAnalysedCol and CrRealisedCol are declared as public as well.
label3.Text is always correct with both column and rows count.
Can someone please help me on that?
Thanks in advance
EDIT 05/03/2020
It look like that when i try to access to the DataGridView from another class by using
Form_VVTool formmain = new Form_VVTool();
dt becomes = null.
I suppose that it is because of InitializeComponent() which is called everytime the above code is executed.
What could be a way to preserve everything from Form_VVTool?
Thanks again
I have a gridview table that has auto generated columns and the rows in those columns can be sorted by clicking the column name since I have "AllowSorting" on. I also have checkbox lists that the user can check or uncheck to filter columns in and out of the table.
The problem is when the user filters the table to whatever columns they want and then they click on any column name, it will sort by that column but it brings back all of the columns that they filtered out.
I am guessing that I need to create a class with GridViewSortEventArgs and make the event grab only the columns the user filters instead of selecting all the columns in the database. I tried this but I don't know if I'm headed in the right direction or not but I also do get an error on GetSortColumnIndex() saying "not all code paths return a value". SQLQueryBuilder() obviously builds the query for the table btw.
private void GridView1_Sorting(object sender, GridViewSortEventArgs e)
{
int sortColumnIndex = GetSortColumnIndex();
if (sortColumnIndex != -1)
SQLQueryBuilder();
}
int GetSortColumnIndex()
{
foreach (DataControlField field in GridView1.Columns)
{
if (field.SortExpression == GridView1.SortExpression)
{
return GridView1.Columns.IndexOf(field);
}
}
}
not all code paths return a value
int GetSortColumnIndex()
{
foreach (DataControlField field in GridView1.Columns)
{
if (field.SortExpression == GridView1.SortExpression)
{
return GridView1.Columns.IndexOf(field);
}
}
}
You only return a value if field.SortExpression == GridView1.SortExpression, so add a return -1; at the end of your method.
As for the filtered values problem, do you account for the filtering in
SQLQueryBuilder();
My guess is you're rebuilding the query from scratch there.
I have a DatagridView which contains row and data. I've added checkboxs to select one of the row (1) and then generate a PDF with the data of the selected row (2) (see picture) :
My code contains a part which check if checkbox is 1 or 0 and then I don't know how to get the data of the "checked row".. See
private void button_generer_pdf_Click(object sender, EventArgs e)
{
List<DataGridViewRow> rows_with_checked_column = new List<DataGridViewRow>();
foreach (DataGridViewRow row in dataGrid_factures.Rows)
{
if (Convert.ToBoolean(row.Cells[column_action.Name].Value) == true)
{
MessageBox.Show("OK!"); // Just to check if it undestands I've checked the row
//And then here I want to get highlighted data on the screenshot to create my Pdf
}
}
//PDF Generation here
The same way you got the data from your selection column "row.Cells[column_action.Name].Value" by changing it to be the right name so maybe
row.Cells["NOM"].Value
or you can use the array number should you know it eg
rows.Cells[3].Value
hi my friend you can use this code for any cell or use a loop for all cells!!!
public void ReadDataFromDataGridView()
{
string value = dataGridView1.SelectedRows[0].Cells["columnName"].Value.ToString();
}
I have a webpage with a gridview attached to it. The gridview allows the user to update individual records. The gridview looks like this:
JobSiteID JobSite1
1 13-03
2 13-04
3 13-06
4 13-09
5 13-15
I created the following record updating event handler:
protected void changeJobSiteRecordsGridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
GridViewRow row = changeJobSiteRecordsGridView.Rows[e.RowIndex];
TextBox txtJobSite = row.FindControl("txtJobSite") as TextBox;
if (txtJobSite != null)
{
using (ABCEntities4 Context = new ABCEntities4())
{
int jobSiteID = Convert.ToInt32(changeJobSiteRecordsGridView.DataKeys[e.RowIndex].Value);
JobSite obj = Context.JobSites.First(x => x.JobSiteID == jobSiteID);
obj.JobSite1 = txtJobSite.Text;
Context.SaveChanges();
changeJobSiteRecordsGridView.EditIndex = -1;
changeJobSiteRecordsGridView.DataSource = Context.JobSites;
changeJobSiteRecordsGridView.DataBind();
}
}
}
Here's my problem:
When I select to update, say row #2, on the first line, the local "row" variable indicates that the RowIndex == 1.
However, in the second line, I expect txtJobSite variable to be populated with "13-04" but VS assigns "null" to the variable.
As a result, the code flows over the if then statement below which isn't what was intended.
Any help would be greatly appreciated.
Thanks.
Check the row's cells property like this:
row.Cells[1].Controls[0]
for the text box. If the '0' index doesn't work, try the 1 index. Then your code would look something like this:
TextBox txtJobSite = (TextBox)row.Cells[1].Controls[1]
I remember running into a similar problem with FindControl. This way, you explicitly find the cell and then the control in the cell.
I have a datagridview that contains list of subjects populated from Subject table from database.Columns include
Select(checkbox),
SubjectId,
SubjectName,
SubjectGroup.
Now I want if a user Selects on any of the desired rows, the corresponding SubjectId's should be added to a List. I have made and inserted into the desired table in the database.
The problem is that the new column of checkboxes I have added to this datagridview is not being detected.
My code is:
foreach (DataGridViewRow row in gvSubjectsOpted.Rows)
{
if (Convert.ToBoolean(gvSubjectsOpted.SelectedRows[0].Cells["SelectId"].Value=true))
{
olist.Add(gvSubjectsOpted.SelectedRows[0].Cells["SubjectId"].Value.ToString());
}
}
Late to the party. I had the same issue with trying to get the checkbox column by name, use the index instead. Here is a linq example assuming the checkbox is column 0 and the stored values for TrueValue and FalseVale are true and false respectively.
var checkedRows = from DataGridViewRow r in gvSubjectsOpted.Rows
where Convert.ToBoolean(r.Cells[0].Value) == true
select r;
foreach (var row in checkedRows)
{
olist.Add(row.Cells["SubjectId"].Value.ToString());
}
I realise this is an old post but I came across it and didn't think it was really answered in an efficient way so I thought I would add my method.
I have a similar block in my windows app. I read the values from the grid when the user clicks a button, and I want to know which rows they checked. As the checkboxes are in Cell 0 and the data I want is in Cell 1, I use the following code. Note the cast: it is important as it allows us the use the Where clause and therefore just a single line of code to get the collection of data. I could use the name of the cells instead of magic index numbers but then it would not fit your app so I put numbers instead (you should use names)
var checkedRows = dataGridView
.Rows
.Cast<DataGridViewRow>()
.Where(x => x.Cells[0].Value.ToString() == "1")
.Select(x => x.Cells[1]);
Note that this will give you an IEnumerable of type DataGridViewCell. If you want you can either add something like .Value.ToString() to the select or do this when you use your collection.
You question is similar to another SO question.
Check the answer of this Datagridview checkboxcolumn value and functionality.
Try this
foreach(GridViewRow r in gvSubjectsOpted.Rows)
{
GridViewCheckBoxColumn c = r.cells[0].Controls[0] as GridViewCheckBoxColumn;
if(c.Checked)
{
//Do something.
}
}
private void button1_Click(object sender, EventArgs e)
{
string subjId;
List<string> lines = new List<string>();
for (int i = 0; i < gvSubjectsList.Rows.Count; i++)
{
bool Ischecked =Convert.ToBoolean(gvSubjectsList.Rows[i].Cells["Select"].Value);
if (Ischecked == true)
{
subjId = gvSubjectsList.Rows[i].Cells["SubjectId"].Value.ToString();
lines.Add(subjId);
}
}
comboBox1.DataSource = lines;
}
//the most important thing is to set 'true' and 'false' values against newly added checkboxcolumn instead of '0' and '1'...that is,
CBColumn.FalseValue = "false";
CBColumn.TrueValue = "true";