Can't select rows in datagridview - c#

I have a method which select rows in datagrid and change value of checkboxcolumn:
foreach (DataGridViewRow gridRow in dataGridView1.Rows)
{
if (_selectedIDs != null)
foreach (long id in _selectedIDs)
{
gridRow.Selected = false;
if ((long)((DataRowView)gridRow.DataBoundItem)["ObjectD"] == id)
gridRow.Selected = true;
}
if (_checkedIDs != null)
foreach (long id in _checkedIDs)
{
((DataRowView)gridRow.DataBoundItem)["Choosen"] = 0;
if ((long)((DataRowView)gridRow.DataBoundItem)["ObjectD"] == id)
((DataRowView)gridRow.DataBoundItem)["Choosen"]=true;
}
}
dataGridView1.Refresh();
When I'm debugging this code I see that it enters in lines
gridRow.Selected = true;
and
((DataRowView)gridRow.DataBoundItem)["Choosen"]=true;
and in quickwatch I see that properties of those rows are changed.
But after execution of this code I still have only one row selected
Does anyone have an idea what's wrong with this code?

In addition to the MultiSelect, you might want to make sure that the class you databind implements the INotifyPropertyChanged interface.
You also could set the selected = false before you start looping, or you will overwrite your selection every time...
foreach (DataGridViewRow gridRow in dataGridView1.Rows)
{
if (_selectedIDs != null)
// *****
gridRow.Selected = false;
// *****
foreach (long id in _selectedIDs)
{
if ((long)((DataRowView)gridRow.DataBoundItem)["ObjectD"] == id)
gridRow.Selected = true;
}
if (_checkedIDs != null)
foreach (long id in _checkedIDs)
{
((DataRowView)gridRow.DataBoundItem)["Choosen"] = 0;
if ((long)((DataRowView)gridRow.DataBoundItem)["ObjectD"] == id)
((DataRowView)gridRow.DataBoundItem)["Choosen"]=true;
}
}

Make sure the DataGridView.MultiSelect property is set to true.

Today, I have this error and have been fixed by set Enabled to true
dataGridView1.Enabled = true;

Related

DataGridView C# windows application(First row not selecting which is checkbox if mouse click on column Header)

Can please any one help me on this. I have developed a c# windows application which has DataGridView first column has checkboxes. if I click on first column header it selects all the row level check boxes except the first row. For selecting all row level check boxes I have an event of dataGridView1_ColumnHeaderMouseClick and the code is:
private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
column.SortMode = DataGridViewColumnSortMode.NotSortable;
}
if (e.ColumnIndex == 0)
{
if (chek == 0)
{
try
{
for (int i = 0; i < dataGridView1.RowCount; i++)
{
string paymentValue = dataGridView1.Rows[i].Cells[18].Value.ToString();
string incmngp = dataGridView1.Rows[i].Cells[20].Value.ToString();
if (paymentValue == "N" && incmngp =="")
{
dataGridView1.Rows[i].Cells[0].Value = 1;
chek = 1;
}
}
if (chek == 1)
{
btn_update.Text = "Update";
}
}
catch (Exception ) { }
}
else if(chek==1)
{
try
{
for (int i = 0; i < dataGridView1.RowCount; i++)
{
dataGridView1.Rows[i].Cells[0].Value = 0;
chek = 0;
}
if (chek == 0)
{
btn_update.Text = "OK";
}
}
catch (Exception) { }
}
}
Note: chek is the variable declared on initialize stage
Set your Selection mode property of data grid view to ColumnHeaderSelect
and make sure all your 'Text' columns have SortMode set to NotSortable
UPDATE 2
In which case, Undo everything I ever told before and do that like this
Before you are assigning any DataTable to dataGridView1.
da.Fill(dt);
dataGridView1.DataSource = dt.DefaultView;
dataGridView1.SelectionMode = DataGridViewSelectionMode.RowHeaderSelect;
foreach(DataGridViewColumn dc in dataGridView1.Columns)
{
dc.SortMode = DataGridViewColumnSortMode.NotSortable;
}
dataGridView1.SelectionMode = DataGridViewSelectionMode.ColumnHeaderSelect;
UPDATE 3
Add an event handler for your dataGridView1's ColumnHeaderMouseClick Event
like below
Add the below code (Generic code if you want to use the same functionality for any column of check boxes)
private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
//Enter your own column index here
if(e.ColumnIndex == 0)
foreach(DataGridViewRow row in dataGridView1.Rows)
foreach (DataGridViewCell cell in row.Cells)
{
//Check if the cell type is of a CheckBoxCell
if (cell.GetType() == typeof(DataGridViewCheckBoxCell))
{
DataGridViewCheckBoxCell c = (DataGridViewCheckBoxCell)cell;
c.TrueValue = "T";
c.FalseValue = "F";
if (c.Value == c.FalseValue|| c.Value == null )
c.Value = c.TrueValue;
else
c.Value = c.FalseValue;
}
}
dataGridView1.RefreshEdit();
}
This is a very bizarre bug in Winforms. The problem more generally applies not to the first row, but to the first selected cell in any row of DataGridViewCheckBoxCell(s). You can select the CheckBox cell by clicking on the check box, or select the cell outside the check box, the behavior is the same. If you select 3 check boxes in the middle of your grid, the first of those three will freeze and not update properly. If you try to clear the selection in code, with a dataGridView1.ClearSelection() method call, it still does not work.
The correct answer is to call datagridview1.RefreshEdit() right after you change the checkbox data. You can't just call it after all changes are made. It must be made for each change in the CheckBox value.
foreach (DataGridViewRow row in Results.Rows)
{
var ck = (DataGridViewCheckBoxCell) row.Cells["check"];
ck.Value = ck.TrueValue;
Results.RefreshEdit();
}

update the database column value based on check box checked in grid view

I want to update the database column value based on check box checked in grid view using asp.net c#
In below coding, chbox showing null reference exception
foreach (GridViewRow rows in grdApproval.Rows)
{
if (Chbox.Checked)
{
int RoleID = Convert.ToInt32(ViewState["RoleID"].ToString());
int TsId = Convert.ToInt32(hfTimesheetId.Value);
var Qry = (from m1 in TSEntity.Roles
where m1.RoleId == RoleID
select m1).FirstOrDefault();
if (Qry != null)
{
var QryEditTimesheet = (from m2 in TSEntity.TimeSheets
where m2.Id == TsId
select m2).FirstOrDefault();
if (QryEditTimesheet != null)
{
QryEditTimesheet.IsApproved = true;
QryEditTimesheet.ApprovedBy = ViewState["EmpName"].ToString();
QryEditTimesheet.ModifiedDate = DateTime.Now;
TSEntity.SaveChanges();
}
}
BindGrid();
}
else
{
BindGrid();
}
}
without any further information, i can just guess.
first i would recommend to change your first line to
foreach(GridViewRow row in grdApproval.Rows)
and second can you try to change your second line to
if(row.Columns["yourcheckboxcolumnnumber"].checked)
hope that helps.

Find a row in dataGridView based on column and value

I have a dataGridView that has 3 columns: SystemId, FirstName, LastName that is bound using database information. I would like to highlight a certain row, which I would do using:
dataGridView1.Rows[????].Selected = true;
The row ID I however do not know and the bindingsource keeps changing, thus row 10 could be "John Smith" in one instance but not even exist in another (I have a filter that filters out the source based on what user enters, so typing in "joh" would yield all rows where first / last name have "joh" in them, thus my list can go from 50 names to 3 in a click).
I want to find a way how I can select a row based on SystemId and a corresponding number. I can get the system ID using the following method:
systemId = dataGridView1.Rows[dataGridView1.CurrentRow.Index].Cells["SystemId"].Value.ToString();
Now I just need to apply it to the row selector. Something like dataGridView1.Columns["SystemId"].IndexOf(systemId} but that does not work (nor does such method exist). Any help is greatly appreciated.
This will give you the gridview row index for the value:
String searchValue = "somestring";
int rowIndex = -1;
foreach(DataGridViewRow row in DataGridView1.Rows)
{
if(row.Cells[1].Value.ToString().Equals(searchValue))
{
rowIndex = row.Index;
break;
}
}
Or a LINQ query
int rowIndex = -1;
DataGridViewRow row = dgv.Rows
.Cast<DataGridViewRow>()
.Where(r => r.Cells["SystemId"].Value.ToString().Equals(searchValue))
.First();
rowIndex = row.Index;
then you can do:
dataGridView1.Rows[rowIndex].Selected = true;
The above answers only work if AllowUserToAddRows is set to false. If that property is set to true, then you will get a NullReferenceException when the loop or Linq query tries to negotiate the new row. I've modified the two accepted answers above to handle AllowUserToAddRows = true.
Loop answer:
String searchValue = "somestring";
int rowIndex = -1;
foreach(DataGridViewRow row in DataGridView1.Rows)
{
if (row.Cells["SystemId"].Value != null) // Need to check for null if new row is exposed
{
if(row.Cells["SystemId"].Value.ToString().Equals(searchValue))
{
rowIndex = row.Index;
break;
}
}
}
LINQ answer:
int rowIndex = -1;
bool tempAllowUserToAddRows = dgv.AllowUserToAddRows;
dgv.AllowUserToAddRows = false; // Turn off or .Value below will throw null exception
DataGridViewRow row = dgv.Rows
.Cast<DataGridViewRow>()
.Where(r => r.Cells["SystemId"].Value.ToString().Equals(searchValue))
.First();
rowIndex = row.Index;
dgv.AllowUserToAddRows = tempAllowUserToAddRows;
Or you can use like this. This may be faster.
int iFindNo = 14;
int j = dataGridView1.Rows.Count-1;
int iRowIndex = -1;
for (int i = 0; i < Convert.ToInt32(dataGridView1.Rows.Count/2) +1; i++)
{
if (Convert.ToInt32(dataGridView1.Rows[i].Cells[0].Value) == iFindNo)
{
iRowIndex = i;
break;
}
if (Convert.ToInt32(dataGridView1.Rows[j].Cells[0].Value) == iFindNo)
{
iRowIndex = j;
break;
}
j--;
}
if (iRowIndex != -1)
MessageBox.Show("Index is " + iRowIndex.ToString());
else
MessageBox.Show("Index not found." );
Try this:
string searchValue = textBox3.Text;
int rowIndex = -1;
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
try
{
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.Cells["peseneli"].Value.ToString().Equals(searchValue))
{
rowIndex = row.Index;
dataGridView1.CurrentCell = dataGridView1.Rows[rowIndex].Cells[0];
dataGridView1.Rows[dataGridView1.CurrentCell.RowIndex].Selected = true;
break;
}
}
}
catch (Exception exc)
{
MessageBox.Show(exc.Message);
}
If you just want to check if that item exists:
IEnumerable<DataGridViewRow> rows = grdPdfs.Rows
.Cast<DataGridViewRow>()
.Where(r => r.Cells["SystemId"].Value.ToString().Equals(searchValue));
if (rows.Count() == 0)
{
// Not Found
}
else
{
// Found
}
This builds on the above answer from Gordon--not all of it is my original work.
What I did was add a more generic method to my static utility class.
public static int MatchingRowIndex(DataGridView dgv, string columnName, string searchValue)
{
int rowIndex = -1;
bool tempAllowUserToAddRows = dgv.AllowUserToAddRows;
dgv.AllowUserToAddRows = false; // Turn off or .Value below will throw null exception
if (dgv.Rows.Count > 0 && dgv.Columns.Count > 0 && dgv.Columns[columnName] != null)
{
DataGridViewRow row = dgv.Rows
.Cast<DataGridViewRow>()
.FirstOrDefault(r => r.Cells[columnName].Value.ToString().Equals(searchValue));
rowIndex = row.Index;
}
dgv.AllowUserToAddRows = tempAllowUserToAddRows;
return rowIndex;
}
Then in whatever form I want to use it, I call the method passing the DataGridView, column name and search value. For simplicity I am converting everything to strings for the search, though it would be easy enough to add overloads for specifying the data types.
private void UndeleteSectionInGrid(string sectionLetter)
{
int sectionRowIndex = UtilityMethods.MatchingRowIndex(dgvSections, "SectionLetter", sectionLetter);
dgvSections.Rows[sectionRowIndex].Cells["DeleteSection"].Value = false;
}
Those who use WPF
for (int i = 0; i < dataGridName.Items.Count; i++)
{
string cellValue= ((DataRowView)dataGridName.Items[i]).Row["columnName"].ToString();
if (cellValue.Equals("Search_string")) // check the search_string is present in the row of ColumnName
{
object item = dataGridName.Items[i];
dataGridName.SelectedItem = item; // selecting the row of dataGridName
dataGridName.ScrollIntoView(item);
break;
}
}
if you want to get the selected row items after this, the follwing code snippet is helpful
DataRowView drv = dataGridName.SelectedItem as DataRowView;
DataRow dr = drv.Row;
string item1= Convert.ToString(dr.ItemArray[0]);// get the first column value from selected row
string item2= Convert.ToString(dr.ItemArray[1]);// get the second column value from selected row
string text = "param";
var rows = dataGridViewlist.Rows.OfType<DataGridViewRow>()
.Select(x => new { Value = x.Cells[6].Value.ToString(), Index = x.Index }).ToList();
var index= rows.Where(w => w.Value == text).Select(s => s.Index).FirstOrDefault();
You can try:
string DT = string.Empty;
try
{
DT = $"{dataGridView1.SelectedRows[0].Cells[1].Value}-{dataGridView1.SelectedRows[0].Cells[2].Value}-{dataGridView1.SelectedRows[0].Cells[3].Value}-{dataGridView1.SelectedRows[0].Cells[4].Value}";
}
catch { }
try
{
dataGridView1.Rows.Cast<DataGridViewRow>().Where(x => $"{x.Cells[1].Value}-{x.Cells[2].Value}-{x.Cells[3].Value}-{x.Cells[4].Value}" == DT).ToList()[0].Selected = true;
}
catch (Exception ex) { }

Code to clear DataGridView

See code below:
foreach (DataGridViewRow r in dgvStatus.Rows)
{
foreach (DataGridViewCell c in r.Cells)
{
c.Value = "";
}
}
Pretty simple, clears all the values. But I need to make some modifications to it and don't know how to go along.
I want it to clear all the values, except for the first cell in every column. Also, some cells contain checkboxes and not textboxes, how can I make a check for this?
Thanks
Try this:
foreach (DataGridViewRow r in dgvStatus.Rows) {
if (r.Index == 0) {
continue;
}
foreach (DataGridViewCell c in r.Cells) {
if c.OwningColumn is DataGridViewCheckBoxColumn) {
continue;
}
c.Value = "";
}
}

How to abort unchecking item at checkedlistbox?

I have a method:
foreach (DataGridViewColumn column in dgvGeoObjectsFirstView.Columns)
{
geoObjectsColumnsCheckedListBoxFirstView.Items.Add(column.HeaderText, column.Visible);
geoObjectsColumnsCheckedListBoxFirstView.ItemCheck += (ss, ee) =>
{
if (geoObjectsColumnsCheckedListBoxFirstView.SelectedItem != "Show")
{
if (geoObjectsColumnsCheckedListBoxFirstView.SelectedItem != null)
{
var selectedItem = geoObjectsColumnsCheckedListBoxFirstView.SelectedItem.ToString();
foreach (DataGridViewColumn column2 in dgvGeoObjectsFirstView.Columns)
{
if (column2.HeaderText == selectedItem.ToString())
{
column2.Visible = ee.NewValue == CheckState.Checked;
}
}
int currentDisplayIndex = 0;
foreach (DataGridViewColumn dataGridViewColumn in dgvGeoObjectsFirstView.Columns)
{
if (dataGridViewColumn.HeaderText == selectedItem)
{
currentDisplayIndex = dataGridViewColumn.Index;
}
}
int futureDisplayIndex = geoObjectsColumnsCheckedListBoxFirstView.SelectedIndex;
PassColumnsInFirstView(futureDisplayIndex, currentDisplayIndex);
}
}
else
{
//What can I do here to have item checked
}
};
}\
The problem is taht one column which header text "Show" shouldn't be uncheckable, so I want something like aborting unchecking for this item.
Maybe some event on checkedlistbox?
Best regards
Make the column read-only and then you needn't fiddle with preventing it from being changed.
Otherwise, subscribe to the CellEndEdit event and set e.Cancel = true.

Categories