How to add columns and Evaluate the value - c#

I have a datagridview (two columns). Columns 1: Name, Columns 2: Age
And I want add more column name Evaluate behind Columns Age when I press Evaluate button.
Content on each row are Young(Old). Young if Age<40 and Old if Age>40
How I do that?
My code:
OpenFileDialog opd = new OpenFileDialog();
private void btnOpenfile_Click(object sender, EventArgs e)
{
//Open txt file
opd.Filter = "TXT|*.txt";
//Choose File
if (opd.ShowDialog() == DialogResult.OK)
{
lblFilename.Text = opd.SafeFileName;
}
var dulieu = File.ReadAllLines(opd.FileName);
////////////////////
if (dulieu.Count() > 0)
{
foreach (var cellValues in dulieu.Skip(0))
{
var cellArray = cellValues
.Split(new[] {'\t'}, StringSplitOptions.RemoveEmptyEntries);
if (cellArray.Length == dtgBangketqua.Columns.Count)
dtgBangketqua.Rows.Add(cellArray);
}
}
}
My Form

Based on your if (cellArray.Length == dtgBangketqua.Columns.Count) I assume you do not already have a "Evaluate" column within your DataGridView. So first thing to do is add one.
Then loop through each row and obtain the age value.
It originally came in as a string, so, you need to cast it to an int.
Then evaluate the age, I assume you did not mean to exclude people who are exactly 40, so I set that as Old.
Here is the code that should work for your need:
private void btnEvaluate_Click(object sender, EventArgs e)
{
dtgBangketqua.Columns.Add("Evaluate", "Evaluate");
foreach (DataGridViewRow ThisRow in dtgBangketqua.Rows)
{
string strAge = ThisRow.Cells[1].Value as string;
int Age = -1;
if( int.TryParse(strAge,out Age) == true )
{
ThisRow.Cells[2].Value = (Age < 40) ? "Young" : "Old";
}
}
}
Don't forget to mark the answer as accepted if it works for you.

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));
}

Input a value from a combobox, while committing an Add in DataGridView

Using C# and forms. I have a datagridview which has two of the three fields visible in the table which is editable and addable. The third field is in a combobox.
When updating the database (hitting enter after adding in the empty row) I get an error saying that the third field can't be null. I'd like to have the value in the combobox be used for the third field.
I can't seem to figure it out. Should I be using an event, somehow?
private void cmbMCID_SelectedIndexChanged(object sender, EventArgs e)
{
var cMarks = (from cm in DB.Student_Courses
where cm.CID == Convert.ToInt32(cmbMCID.Text)
select cm).ToList();
Student_Course sc = new Student_Course();
//cMarks.Add(sc);
studentCourseBindingSource.DataSource = cMarks;
sc.CID = Convert.ToInt32(cmbMCID.Text);
//studentCourseBindingSource.ResetBindings(false);
}
I've attempted to added a RowsAdded Event but didn't come out on top.
private void dgvSMarks_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
if (tabControl1.SelectedIndex == 3)
{
Student_Course sc = new Student_Course();
sc.CID = Convert.ToInt32(cmbMCID.Text);
}
}
Great, OK. so I was doing horrible things - with the combobox. A mix of needing to making a selection in the combobox first (otherwise returned null) and trying to commit what was already in the database.
Needed to create a for loop through the dgv collection, too.
private void dgvSMarks_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
// if (dgvSMarks.ContainsFocus == true)
// {
// // Get the RowIndex of the CID Cell, and add the combobox MCID value to it
// dgvSMarks.Rows[e.RowIndex-1].Cells[0].Value = Convert.ToInt32(cmbMCID.Text);
// }
var student_course = new Student_Course();
var course = new Course();
//MessageBox.Show("Row Count is " + dgvSMarks.Rows.Count);
for (int i = 1; i < dgvSMarks.Rows.Count; i++)
{
if (i == (dgvSMarks.Rows.Count - 1))
{
student_course.CID = Convert.ToInt32(cmbMCID.Text);
student_course.SID = Convert.ToInt32(dgvSMarks.Rows[i - 1].Cells[1].Value);
student_course.Mark = Convert.ToInt32(dgvSMarks.Rows[i - 1].Cells[2].Value);
DB.Student_Courses.InsertOnSubmit(student_course);
DB.SubmitChanges();
}
}
}
Thanks to the help of my CPI instructors. :)

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 = "";
}
}

If all rows data is null hide column

Using MS Visual Studio 2012, Telerik, C#.ASP.NET.
The logic I need is as follows:
If a columns data on all rows is null then hide the column
Basically if a column has 3 rows of data, if there all null then dont bother displaying that column, however if there is a value in 1 of them, then show the column.
been playing around:
foreach (GridColumn columns in dgvUserResults.Columns)
{
if (columns != null)
{
columns.Visible = false;
}
else
{
columns.Visible = true;
}
}
code doesn't work of course doesnt iterate through the foreach loop just skips it. Although not bothered about that even if it did iterate through I need a way to check if all column[name] rows are null. There a nice Telerik one liner?
Please try with below code snippet.
Using UniqueName
protected void RadGrid1_PreRender(object sender, EventArgs e)
{
foreach (GridColumn column in RadGrid1.MasterTableView.Columns)
{
// If you used ClientSelectColumn then below code is not worked For that you have to put condition
//if(column.ColumnType == "GridBoundColumn")
int TotalNullRecords = (from item in RadGrid1.MasterTableView.Items.Cast<GridDataItem>()
where string.IsNullOrWhiteSpace(item[column.UniqueName].Text) ||
item[column.UniqueName].Text == " "
select item).ToList().Count;
if (TotalNullRecords == RadGrid1.MasterTableView.Items.Count)
{
RadGrid1.MasterTableView.Columns.FindByUniqueName(column.UniqueName).Visible = false;
}
}
}
By Using Index
protected void RadGrid1_PreRender(object sender, EventArgs e)
{
foreach (GridColumn column in RadGrid1.MasterTableView.Columns)
{
// If you used ClientSelectColumn then below code is not worked For that you have to put condition
//if(column.ColumnType == "GridBoundColumn")
int TotalNullRecords = (from item in RadGrid1.MasterTableView.Items.Cast<GridDataItem>()
where string.IsNullOrWhiteSpace(item[column.UniqueName].Text) ||
item[column.UniqueName].Text == " "
select item).ToList().Count;
if (TotalNullRecords == RadGrid1.MasterTableView.Items.Count)
{
column.Visible = false;
}
}
}
For col = 0 To myRadGridView.ColumnCount
Dim mustKeepColumn As Boolean = False
For Each r In myRadGridView.Rows
If Not String.IsNullOrEmpty(r.Cells(col).Value.ToString) Then
mustKeepColumn = True
Exit For
End If
Next
If Not mustKeepColumn Then
myRadGridView.Columns(col).IsVisible = False
End If
Next

Categories