Getting the value from a specific Gridview Cell - c#

I'm trying to access the value of a cell in my GridView. I want to access the value by the cell's name, rather than by the index. How can I do this?
I do not want to access the cell by its index because there is a chance that it will change positions at any time. I know that Cells[0] would give me the value of the first index, but how about if I want to do something like Cells["NameOfCell"]?
Note: I cannot use the GridView events because all the existing code is doing it in a function called Bind() and they have something like this
public void Bind()
{
foreach (GridViewRow row in GridView1.Rows)
{
//need to access the specific value here by name
//I know this is wrong but you get the idea
string test = row.Cells["NameOfCell"].ToString();
}
}

just 4 fun:
private int nameCellIndex = -1;
private const string CellName = "Name";
void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
for (int cellIndex = 0; cellIndex < e.Row.Cells.Count; cellIndex++)
{
if (e.Row.Cells[cellIndex].Text == CellName)
{
nameCellIndex = cellIndex;
break;
}
}
}
else if (nameCellIndex != -1 && e.Row.RowType == DataControlRowType.DataRow)
{
string test = e.Row.Cells[nameCellIndex].Text;
}
}
the same, not using RowDataBound:
private int nameCellIndex = -1;
private const string CellName = "Name";
void Button1_Click(object sender, EventArgs e)
{
for (int cellIndex = 0; cellIndex < GridView1.HeaderRow.Cells.Count; cellIndex++)
{
if (GridView1.HeaderRow.Cells[cellIndex].Text == CellName)
{
nameCellIndex = cellIndex;
break;
}
}
if (nameCellIndex != -1)
{
foreach (var row in GridView1.Rows.OfType<GridViewRow>().Where(row => row.RowType == DataControlRowType.DataRow))
{
string test = row.Cells[nameCellIndex].Text;
}
}
}

If possible, get the data from your data source - the GridView should be used for displaying data and not retrieving it. It's bound to your data source, so you should be well-equipped to read from the data source too.

You can get the value from the GridView Row DataItem
See here: http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridviewrow.dataitem.aspx

Related

c# how to get the values next to checked datagridview checkboxes?

I have a DataGridView with CheckBox column, my question is how do I get the data next to a checked checkboxes and assign them to a variables in array?
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
foreach (DataGridViewRow row in this.dataGridView1.Rows)
{
if (Convert.ToBoolean(this.dataGridView1.Rows[e.RowIndex].Cells["chkBoxColumn"].Value = true) == true)
{
MessageBox.Show(dataGridView1.Rows[e.RowIndex].Cells[1].Value.ToString());
}
}
}
It prints the last checked item over and over.
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
if (bool.Parse(dataGridView1.Rows[i].Cells["chkBoxColumn"].Value.ToString()) == true)
{
MessageBox.Show(dataGridView1.Rows[i].Cells[1].Value.ToString());
}
}
}
and i'm getting a null reference exception using this.
Edit
Question got changed, so tweaked the code so that the values get put into a list.
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
List<string> someList = new List<string>();
foreach (DataGridViewRow row in this.dataGridView1.Rows)
{
var cell = row.Cells[e.ColumnIndex] as DataGridViewCheckBoxCell;
if (Convert.ToBoolean(cell.Value) == true)
{
if (cell.State != DataGridViewElementStates.Selected)
{
someList.Add(row.Cells[1].Value.ToString();
}
}
else if (cell.State == DataGridViewElementStates.Selected)
{
someList.Add(row.Cells[1].Value.ToString();
}
}
}
This might do the trick for you, however you'll get a popup every time a user ticks a checkbox, and you'll get as many popup as there are checkboxes that are true.
the problem is in the line
MessageBox.Show(dataGridView1.Rows[e.RowIndex].Cells[1].Value.ToString());
e.RowIndex points to the changed row
it should be:
for (int i = 0; i <= this.dataGridView1.Rows)
{
var row = this.dataGridView1.Rows[i]
if (Convert.ToBoolean(this.dataGridView1.Rows[i].Cells["chkBoxColumn"].Value = true) == true)
{
MessageBox.Show(dataGridView1.Rows[e.RowIndex].Cells[1].Value.ToString());
}
}
Also, note that you're getting error in your second example because some row is containing a null value in the checkbox column.
Convert.ToBoolean(null) returns false
But bool.Parse(null) throws an exception
I guess something like this ?
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
Stringbuilder text = new StringBuilder();
foreach (DataGridViewRow row in this.dataGridView1.Rows)
{
if (Convert.ToBoolean(row.Cells["chkBoxColumn"].Value = true) == true)
{
text.Append(row.Cells[1].Value.ToString());
}
}
MessageBox.Show(text.ToString());
}
EDIT: the question has changed from showing the values to saving them into an array, so I need to change my answer also
Suppose you want all values for Cell[1] saved into an array
and suppose that cell is of type integer.
private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
List<int> list = new List<int>();
foreach (DataGridViewRow row in this.dataGridView1.Rows)
{
if (Convert.ToBoolean(row.Cells["chkBoxColumn"].Value = true) == true)
{
list.Add(int.Parse(row.Cells[1].Value.ToString()));
}
}
// you now have all values saved into the list
}
You can put the code in a button click and find checked values this way:
private void button1_Click(object sender, EventArgs e)
{
var checkedValues = dataGridView1.Rows.Cast<DataGridViewRow>()
.Where(row => (bool?)row.Cells["Your CheckBox Column Name"].Value == true)
.Select(row => string.Format("{0}", row.Cells["The Other Column Name"].Value))
.ToList();
MessageBox.Show(string.Join(",", checkedValues));
}

hide empty row in gridview

I want to hide empty row in one particular column. I tried to but negative. Below is my code:
protected void gvDb_DataBound(object sender, EventArgs e)
{
foreach (GridViewRow rw in gvDb.Rows)
{
if ((string.IsNullOrEmpty(rw.Cells[1].Text) | (rw.Cells[1].Text == "")))
{
rw.Visible = false;
}
}
}
for (int i = 0; i < gvDb.RowCount - 1; i++)
{
var row = gvDb.Rows[i];
if (string.IsNullOrEmpty(Convert.ToString(row.Cells[1].Value)))
{
row.Visible = false;
}
}
This will work,
use for instead of foreach to iterate all the rows except last row which is empty.

DevExpress Winform - How to compare data between two gridcontrol on multiple key field

I have 2 gridControl and I wanna change background of cells (rows) that different between 2 gridControl with primary key is multiple field set by user.
Any solution for this problem?
See this example image
In this two query, key field is col1, col2, col3 and col4. Different in col6 and I want to highlight cell that have different value.
This is my current code for RowCellStyle event
private void gvQuery1_RowCellStyle(object sender, RowCellStyleEventArgs e)
{
if (gcQuery2.DataSource == null || lsKey == null || lsKey.Count <= 0)
return;
List<object> id = new List<object>();
foreach (KeyObject key in lsKey)
{
id.Add((sender as GridView).GetRowCellValue(e.RowHandle, key.key1[1].ToString()));
}
for (int i = 0; i < gvQuery2.RowCount; i++)
{
int rowHandle = gvQuery2.GetVisibleRowHandle(i);
bool flgEqual = true;
for (int j = 0; j < lsKey.Count; j++)
{
object v = gvQuery2.GetRowCellValue(rowHandle, gvQuery2.VisibleColumns[int.Parse(lsKey[j].key2[0].ToString())]);
if (id[j] == null && v == null)
continue;
if (!id[j].GetType().Equals(v.GetType()) || !id[j].ToString().Equals(v.ToString()))
{
flgEqual = false;
break;
}
}
if (flgEqual)
{
for (int k = 0; k < (sender as GridView).Columns.Count; k++)
{
if (!(sender as GridView).GetRowCellValue(e.RowHandle, (sender as GridView).Columns[k].FieldName).ToString()
.Equals(gvQuery2.GetRowCellValue(rowHandle, (sender as GridView).Columns[k].FieldName).ToString()))
{
if (e.Column.FieldName.Equals((sender as GridView).Columns[k].FieldName))
e.Appearance.BackColor = Color.Orange;
}
}
break;
}
}
}
Refer this: Customizing Appearances of Individual Rows and Cells
You can implement your functionality using the
GridView.RowCellStyle event. This event is fired for each cell in
a Grid View and thus it has Column and RowHandle parameters
that identify the cell being painted.
I assume that you have fixed number of records in both grid and also the order of the records are same. Then you can try to user same row handle to access the value from the both grid's MainView at RowCellStyle event as below:
using DevExpress.XtraGrid.Views.Grid;
// ...
private void gridView1_RowCellStyle(object sender, RowCellStyleEventArgs e) {
GridView View = sender as GridView;
GridView leftGridView = leftGrid.MainView as GridView; //It is up to you that which viewtype you have used.
if(e.Column.FieldName == "Col5") {
string srcVal= View.GetRowCellDisplayText(e.RowHandle, View.Columns["Col5"]); // You can use GetRowCellValue() method also to get the value from the cell.
string leftGridVal= leftGridView .GetRowCellDisplayText(e.RowHandle, leftGridView .Columns["Col5"]);
if(srcVal != leftGridVal) {
e.Appearance.BackColor = Color.DeepSkyBlue;
e.Appearance.BackColor2 = Color.LightCyan;
}
}
}
Above code snippet is just like a sudo code to direct you to implement the functionality.. Handle this event on that Grid on which you want to color.. Remember to take care about the RowHandle, you have take care about the row index.
Hope this help..
Use the GridView.RowCellStyle event, which enables appearance settings of individual cells to be changed
Please refer this site for your reference
https://www.devexpress.com/Support/Center/Question/Details/Q520842
void gridView1_RowCellStyle(object sender, RowCellStyleEventArgs e)
{
GridView currentView = sender as GridView;
if (e.Column.FieldName == "Customer")
{
bool value = Convert.ToBoolean(currentView.GetRowCellValue(e.RowHandle, "Flag_Customer"));
if (value)
e.Appearance.BackColor = Color.Red;
}
if (e.Column.FieldName == "Vendor")
{
bool value = Convert.ToBoolean(currentView.GetRowCellValue(e.RowHandle, "Flat_Vendor"));
if (value)
e.Appearance.BackColor = Color.Red;
}
}

Compare Old Cell and New cell values in datagridview

I have a DataGridView. I have to compare the old and the new cell values and perform further action.
I tried comparing with Cell Leave, CellValidating events by using the following code,
private void TestGrid_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
int currentCell = TestGrid.CurrentCell.ColumnIndex;
var oldCellValue = TestGrid[e.ColumnIndex, e.RowIndex].Value;
var newValue = e.FormattedValue;
}
It returns my Old value and new value both as eg: 1000 when I try clicking on the different cell.
Please, let me know if there is any other event through which I can achieve the desired behaviour.
Also If I have to compare the old and new cells row or column indexes then how to proceed?
private void TestGrid_CellLeave(object sender, DataGridViewCellEventArgs e)
{
int currentCell = TestGrid.CurrentCell.ColumnIndex;
int oldCell = e.ColumnIndex;
}
Both them returns same index.
Try converting the cell values into strings and do something similar like this (code example comes from MSDN). Hope this helps.
// Iterate through the SelectedCells collection and sum up the values.
for (counter = 0;
counter < (DataGridView1.SelectedCells.Count); counter++)
{
if (DataGridView1.SelectedCells[counter].FormattedValueType ==
Type.GetType("System.String"))
{
string value = null;
// If the cell contains a value that has not been commited,
// use the modified value.
if (DataGridView1.IsCurrentCellDirty == true)
{
value = DataGridView1.SelectedCells[counter]
.EditedFormattedValue.ToString();
}
else
{
value = DataGridView1.SelectedCells[counter]
.FormattedValue.ToString();
}
if (value != null)
{
// Ignore cells in the Description column.
if (DataGridView1.SelectedCells[counter].ColumnIndex !=
DataGridView1.Columns["Description"].Index)
{
if (value.Length != 0)
{
SelectedCellTotal += int.Parse(value);
}
}
}
}
Try with the EditedFormattedValue property of the DataGridView. Tested this one and I see the different values:
private void TestGrid_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
int currentCell = TestGrid.CurrentCell.ColumnIndex;
var oldValue = TestGrid[e.ColumnIndex, e.RowIndex].Value;
var newValue = TestGrid[e.ColumnIndex, e.RowIndex].EditedFormattedValue;
/* Perform some logic here*/
}

How to validate datagridview input by the value type of column in c#?

I am trying to validate datagridview input by the value type of respective column, this is my code:
private void dgvLoadTable_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
foreach (DataGridViewRow dr in dgvLoadTable.Rows)
{
foreach (DataGridViewCell dc in dr.Cells)
{
if (dc.GetType() == typeof(Int32) || dc.GetType() == typeof(Double))//if(dc.ColumnIndex==0)
{
DataGridViewTextBoxCell cell = dgvLoadTable[e.ColumnIndex, e.RowIndex] as DataGridViewTextBoxCell;
if (cell != null)
{
char[] chars = e.FormattedValue.ToString().ToCharArray();
foreach (char c in chars)
{
if (char.IsDigit(c) == false)
{
MessageBox.Show("You have to enter digits only");
e.Cancel = true;
break;
}} }
}
}
}
}
But this is not working, what should be the type for a number column? FYI, this is an winForm application and different data is loaded in the datagridview on runtime by user choice. So columns are not known previously. The datagridview is bound to an entity model.
First this depends on a datatype in your source collection.
So it may be decimal or some other numeric values.
Best if you put conditional a breakpoint in this method for certain cell (column).
Also I would avoid iterating thru each row anc column because this method is called for specific cell.
So rather than doing foreach for row / cell you may want to get exact data for cell by using e.RowIndex and e.ColumnIndex to extract cell data object from your data source.
My src looks is a list of objects:
class TestData
{
public Decimal Value { get; set; }
public string Name { get; set; }
}
Initialized like this:
List<TestData> src = new List<TestData>();
src.Add(new TestData() { Name = "Test 1", Value = 10 });
src.Add(new TestData() { Name = "Test 2", Value = 20 });
dataGridView1.DataSource = src;
And my test can be done here:
private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
var row = dataGridView1.Rows[e.RowIndex];
if ( null != row)
{
var cell = row.Cells[e.ColumnIndex];
if ( null != cell)
{
object value = cell.Value;
if ( null != value )
{
// Do your test here in combination with columnindex etc
}
}
}
}
private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
foreach (DataGridViewRow dr in dataGridView1.Rows)
{
foreach (DataGridViewCell dc in dr.Cells)
{
int x;
double y;
if (int.TryParse(dc.Value.ToString(),out x) || double.TryParse(dc.Value.ToString(),out y))
{
MessageBox.Show("You have to enter digits only");
}
}
}
}
I hope this helps you. I recommend you use the tryparse functions to see if the value entered is a number or not. You may use this function for DataGridView_CellValueChanged function as well.
Sorry about the last one, here is a new block of code. I've tried it its working.
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
int x;
if (this.Visible && !int.TryParse(dataGridView1[e.ColumnIndex, e.RowIndex].Value.ToString(), out x))
{
MessageBox.Show("You have to enter digits only");
dataGridView1[e.ColumnIndex, e.RowIndex].Value = "";
}
}

Categories