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.
Related
I have a User Control with an Ultragrid. In a particular form where I add a ValueList. The value list will not show for the particular column I'm interested in. If I then code in another column instead by changing the index value for columns I get the value list in the column.
The code looks like:
private void AddCombo(object sender, UcUltraGen.RowClickArgs e)
{
ValueList vl;
if (!ucUltraGridMain.Grid.DisplayLayout.ValueLists.Exists("Texas"))
{
vl = ucUltraGridMain.Grid.DisplayLayout.ValueLists.Add("Texas");
}
else
{
vl = ucUltraGridMain.Grid.DisplayLayout.ValueLists["Texas"];
}
var row = e.VariantRow;
List<PcBase> list = PcBase.PcBaseList.Where(x => x.VariantId == row.Cells["Id"].Text).ToList();
AddValueList(list, vl);
ucUltraGridMain.Grid.DisplayLayout.Bands[0].Columns[1].ValueList =
ucUltraGridMain.Grid.DisplayLayout.ValueLists["Texas"];
And if I change to
...
ucUltraGridMain.Grid.DisplayLayout.Bands[0].Columns[2]
It works. How can I have changed the behavior of columns[1]?
The property in column[1] was read only that is it only had a "get" implemented. By adding a set it worked. Hope this helps someone.
There are different methods to get the index of a datagridview column in C#, for example:
dataGridViewTextBoxColumn1.Index;
dataGridViewTextBoxColumn1.DisplayIndex;
datagridview1.Columns[column.name].Index;
datagridview1.Columns[column.name].DisplayIndex;
The dataGridViewTextBoxColumn1 is inside the DataGridViewColumnsCollection List.
Desingner Code:
this.datagridview1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.dataGridViewTextBoxColumn1,
this.dataGridViewTextBoxColumn2,
this.dataGridViewTextBoxColumn3
}
I was experiencing the different methods, but in strange cases I obtain differents values, for example I use this:
datagridview1.Columns[dataGridViewTextBoxColumn1.name].Index;
I get the real index relative to the column collection, in my test the value is 3.
but if I use this:
dataGridViewTextBoxColumn1.Index;
I get a distinct index, in my test the value is 1.
I do not understand that, because in theory is the same property, doesn't it?,
in case of the displayindex property the result is similar. In my datagridview I have invisible and read only columns.
In other tests, I get the correct values for all cases, and this datagridivew contains more visible and invisible columns to.
My question is: what is the best method for get the correct index of the column in a DataGridView, if I use the events, for example CellContentClick to equalize the DataGridViewCellEventArgs.ColumnIndex?
example:
private void datagridview1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0 && e.ColumnIndex.Equals(datagridview1.Columns[dataGridViewTextBoxColumn1.Name].Index))
datagridview1.Rows[e.RowIndex].Cells[dataGridViewTextBoxColumn2.Index].Value = true;
}
UPDATE
this is my test is a visual studio watch:
TEST 1:
private void dgvTerminales_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0 && e.ColumnIndex.Equals(dgvTerminales.Columns[clmActiva.Name].Index))
dgvTerminales.Rows[e.RowIndex].Cells[clmEditado.Index].Value = true;
}
TEST 2:
Other datagridview with same properties, columns and form.
private void dgvSucursales_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0 && e.ColumnIndex.Equals(dgvSucursales.Columns[clmActiva.Name].Index))
dgvSucursales.Rows[e.RowIndex].Cells[0].Value = true;
}
clmActiva is a DataGridViewCheckBoxColumn column type.
Update # I lost count
Index
Gets the relative position of the band within the DataGridView control.
The value of this property does not necessarily correspond to the current visual position of the band within the collection. For example, if the user reorders columns in a DataGridView at run time (assuming the AllowUserToOrderColumns property is set to true), the value of the Index property of each column will not change. Instead, the column DisplayIndex values change. Sorting rows, however, does change their Index values.
DisplayIndex
Gets or sets the display order of the column relative to the currently displayed columns.
Unlike the Index property, the DisplayIndex property corresponds to the current position of the column as displayed by the user interface (UI). By default, each column's DisplayIndex is set to numbers of increasing order, which reflects the order in which they were added. The Visible property value does not affect the DisplayIndex value.
Update
Ok so it seems the OP left out his exact code which makes this next to impossible to help but after all of the comments in this thread, here goes my next set of results.
The OP is using a DataGridViewCheckBoxColumn so in fact by using CellContentClick this is not incorrect. Changing the CheckBox value will properly fire this event.
The order of events fired would follow CellClick, CellContentClick
Now that this is out of the way, Next
Without having your exact code and trying to piece it together I have the following. (Note because I change these names in the designer, if you try to edit it in the UI it causes issues but I was matching what OP provided so as long as these are adjust in designer.cs itself it works fine lol. The visual designer will yell at you trying to use these names)
this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewCheckBoxColumn();
this.dataGridViewTextBoxColumn2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridViewTextBoxColumn3 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.dataGridViewCheckBoxColumn1,
this.dataGridViewTextBoxColumn2,
this.dataGridViewTextBoxColumn3});
So my DataGridView has 1 CheckBox and 2 Text Columns
below registers all values as 0 when I click the first column with the checkbox which is correct. The event will not fire on TextBox columns.
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
int a = e.ColumnIndex;
int b = dataGridView1.Columns[dataGridViewCheckBoxColumn1.Name].Index;
int c = dataGridViewCheckBoxColumn1.Index;
if (e.RowIndex >= 0 && e.ColumnIndex.Equals(dataGridView1.Columns[dataGridViewCheckBoxColumn1.Name].Index))
dataGridView1.Rows[e.RowIndex].Cells[dataGridViewTextBoxColumn2.Index].Value = true;
}
When I change the position of the CheckBox to be the second column in the grid rather than the first. Then the above values register as all 1 which is correct again.
I don't see any issues. Please again provide us with your exact code, controls ...etc. There is still something missing we can't see as there isn't an issue with what you are providing.
Clearly (if you are getting different results),
column.Index;
Is not pointing to the same instance as:
datagridview1.Columns[column.name].Index;
To prove it display the .GetHashCode() value of both.
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";
I want to select row of previously selected rows after some event my code is as below.
int currentRow = dgvIcbSubsInfo.CurrentCell.RowIndex;
//code to execute
dgvIcbSubsInfo.Rows[currentRow].Selected = true;
after executing the code the preview will be as below. but i need to get the symbol > in id = 1272741 (blue selection) and not in 1272737
Probably you might have taken a look at the DataGridView.CurrentRow Property, which is a read-only property:
Gets the row containing the current cell.
But in the remarks section, there is written:
To change the current row, you must set the CurrentCell property to a
cell in the desired row.
Also, from the DataGridView.CurrentCell Property, we find out that:
When you change the value of this property, the SelectionChanged event
occurs before the CurrentCellChanged event. Any SelectionChanged event
handler accessing the CurrentCell property at this time will get its
previous value.
So, there is no need that you actually select the currentRow becasue it will be selected when you set the CurrentCell value (unless you have some code to be executed inside the current scope between the SelectionChanged and CurrentCellChanged events). Try this:
//dgvIcbSubsInfo.Rows[currentRow].Selected = true;
dgvIcbSubsInfo.CurrentCell = dgvIcbSubsInfo.Rows[currentRow].Cells[0];
I think you wish to highlight the row. Please try following code, I think it might help:
Color color = dgv.Rows[prevRowIndex].DefaultCellStyle.SelectionBackColor;
dgv.Rows[curRowIndex].DefaultCellStyle.SelectionBackColor = color;
Try the following to change the current row. Since the OP is a little unclear as to what row should be the new row, my example simply shows moving from the current row to the previous row (if there is a previous row). The first line of code is optional. You can also hardcode col to 0 (or some other column) to use a fixed column if you don't want to use FullRowSelect.
dataGridView.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
int row = dataGridView.CurrentCell.RowIndex;
int firstRow = dataGridView.Rows.GetFirstRow(DataGridViewElementStates.None);
if (row != firstRow)
{
row--;
int col = dataGridView.CurrentCell.ColumnIndex;
dataGridView.CurrentCell = dataGridView[col, row];
}
I came here wanting to learn how to programmatically select rows in a DataGridView control. Here is how to select the top row in your DataGridView control named dg1 and "click" it:
dg1.Rows[0].Selected = true;
dg1_RowHeaderMouseClick(null, null);
This then calls the following event which is expecting one selected row.
private void dg1_RowHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
var selectedRows = dg1.SelectedRows;
// Make sure we have a single row selected
int count = selectedRows.Count;
if (count == 1)
{
tbAssemblyName.Text = dg1.SelectedRows[0].Cells[0].Value.ToString();
}
}
I had everything working when the user clicked the row they wanted. When there was only one record to choose from I wanted to "click" it for the user.
I have a DataGridView with a Binding-Source bound to a Data-Table loaded from an Oracle-Database. (btw. I don't think that the Database-Connection could cause this)
I have also a DataGridViewComboBoxColumn bound to an class of persons (only "has" ID and name), so I can display / allow to edit the name instead of the ID. My problem is now that after the data-binding is completed c# automatically "selects" the first cell of the DGV - see the attached picture.
I also have to use this little piece of code to ensure data integrity:
private void _table_ColumnChanging(object sender, DataColumnChangeEventArgs e)
{
if (e.Column == _table.Columns["NEEDED_ID"])
{
if (e.ProposedValue == null)
{
e.ProposedValue = System.DBNull.Value;
}
}
}
Now using this _table.GetChanges() always returns the first row of the DGV as "modified" but the value isn't really changed - it's only DBNull instead of null. Can I somehow avoid automatic selection of first cell or how to avoid this behavior?
EDIT: Meanwhile I found out that changing the first column to something not editable fixes this problem. But this is nothing more than an workaround. I would really appreciate to get an working solution for this.
EDIT 2: I have also an empty Object 'on top' of the ComboBox-DataSource
DtoPerson blankPerson = new DtoPerson();
blankPerson.Name = String.Empty;
blankPerson.PersonRollenId = -1;
personList.Add(blankPerson);
Try to put a null in your DataGridViewComboBoxColumn's DataSource. example:
SELECT id, description
FROM yourTable
UNION
SELECT NULL, NULL
GridViewName.ClearSelection();