All, I want to catch the event after I finish input the value of DataGridView cell so that I can validate the value. Is there any event DataGridView when focus-lose happen? What is the best way to make it? thanks.
You should use CellValidating event for this, see here MSDN.
Occurs when a cell loses input focus, enabling content validation.
and example (from MSDN as well)
private void dataGridView1_CellValidating(object sender,
DataGridViewCellValidatingEventArgs e)
{
dataGridView1.Rows[e.RowIndex].ErrorText = "";
int newInteger;
// Don't try to validate the 'new row' until finished
// editing since there
// is not any point in validating its initial value.
if (dataGridView1.Rows[e.RowIndex].IsNewRow) { return; }
if (!int.TryParse(e.FormattedValue.ToString(),
out newInteger) || newInteger < 0)
{
e.Cancel = true;
dataGridView1.Rows[e.RowIndex].ErrorText = "the value must be a non-negative integer";
}
}
Related
I am having a bit of an issue with the datagridview's CellEndEdit event. While I understand the concept of what the issue actually is, any attempt at circumventing it seems to fail.
Basically, I have a datagridview, in the CellEndEdit event, I make a check against the database to make sure the entry is not a duplicate. If it is, I prompt the user with a messagebox to tell them they can't enter duplicates, I then change the value back to its original state/value programmatically, and return the cell to an "Edit" state.
My understanding is that the fact that i'm changing the value programatically is why the event fires twice. To circumvent, I set a flag upon first entering the event, then prompt + set + re-edit, then set the flag to false. This does not work... can anyone tell me why or how I can make this happen?
Here's the event code:
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
if(e.ColumnIndex == this.dataGridView1.Columns["Name"].ColumnIndex)
{
if(!this.CellBeingEdited)
{
string NewName = this.dataGridView1.Rows[e.RowIndex].Cells["Name"].Value.ToString();
//-== DATABASE CODE REMOVED ==-
bool IsDuplicate = ...;
if(IsDuplicate)
{
MessageBox.Show("Cannot have duplicate item names at this level!");
this.dataGridView1.CurrentCell = this.dataGridView1.Rows[e.RowIndex].Cells["Name"];
this.CellBeingEdited = true;
this.dataGridView1.CurrentCell.Value = this.LastEditedRowName;
this.CellBeingEdited = false;
this.dataGridView1.BeginEdit(false);
return;
}
}
}
}
This bit of code does not fire twice when I edit a value in a row :
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
string test = "test";
if (this.dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString() == test)
{
this.dataGridView1.CurrentCell = this.dataGridView1.Rows[e.RowIndex].Cells[0];
this.dataGridView1.CurrentCell.Value = "not test";
this.dataGridView1.BeginEdit(false);
return;
}
}
Perhaps are you calling the event elsewhere?
my goal is to have a friendly validation flow on my DataGridView.
When the user enters an incorrect value for a certain cell, I want to:
exit editing mode
revert the modification (i.e. recover the original value from the cell)
display an error message
I am currently using the CellValidating event to prevent the cell from updating its value but I'm not able to exit the editing mode. The cell is then waiting for a correct value and won't let the user to simply cancel&revert his action...
Here is what the validation method looks like :
private void dataGridViewMsg_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
[...] // Here, treatment determines is the new cell value isValid or not
if (!isValid)
{
MessageBox.Show("The value entered is incorrect.", "Modification aborted");
e.Cancel = true;
dataGridViewMsg[e.ColumnIndex, e.RowIndex].IsInEditMode = false; // Someway, what I would like to do
return;
}
}
How can I proceed to make the cell recover its original value without requiring me to keep track of this value?
You can use EndEdit() to get what you want.
In any case, note that it is better to make sure that the cancellation happens only under the expected conditions; otherwise, the code might get stuck in this event because it is automatically called at many different points. For example, to validate the inputs written by the user via cell edition, you can rely on an approach on the lines of the following one:
bool cancelIt = false;
private void dataGridViewMsg_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
[...] // Here, treatment determines is the new cell value isValid or not
if (cancelIt && !isValid)
{
MessageBox.Show("The value entered is incorrect.", "Modification aborted");
e.Cancel = true;
dataGridViewMsg.EndEdit();
cancelIt = false;
}
}
//CellBeginEdit event -> the user has edited the cell and the cancellation part
//can be executed without any problem
private void dataGridViewMsg_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
cancelIt = true;
}
I am writing a C# application that uses a DataGridView and I would like to validate the input each time a user changes the data that's there.
I began by using the CellValidating event which has a really nice CancelEdit() method that will return the cell to its previous value. However, this event is fired every time the user leaves the cell, regardless of whether or not it has changed.
Does CellValueChanged support a sort of cancel or rollback method to the previous value? This way I would be able to still validate the data, but not waste time with cells that didn't need it, but would prefer not to sacrifice the ability to restore the cell if data is invalid.
Here is a bit of code:
private void dataGrid1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
if(dataGrid1.Columns[e.ColumnIndex].Name == "dateColumn")
{
String input = e.FormattedValue.ToString();
// Split the date from MM/DD/YYYY format
String[] temps = input.Split('/');
try
{
if(temps[2].Length != 4)
MessageBox.Show("The year entered is not the correct length.", "Invalid Year", MessageBoxButtons.OK);
DateTime date = new DateTime(Convert.ToInt32(temps[2]), Convert.ToInt32(temps[0]), Convert.ToInt32(temps[1]));
}
catch (Exception ex) // If exception is thrown, date was invalid
{
MessageBox.Show("The date entered was invalid.", "Invalid date", MessageBoxButtons.OK);
dataGrid1.CancelEdit(); // Set cell value back to what it was prior to user's change
e.Cancel = true; // Have focus stays with this cell rather than move down a row.
}
}
}
You could try another aproach like this:
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
newvalue = (int)dataGridView1[e.ColumnIndex, e.RowIndex].Value;
}
private void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
oldvalue = (int)dataGridView1[e.ColumnIndex, e.RowIndex].Value;
}
Assuming its an int,if its another datatype then will also work(except offcourse the variables oldvalue and newvalue must be that type also).
Or by your question,its just about the old value,then you will only need the CellBeginEdit event and then use the oldvalue variable inside the validating event.
IMHO better solution, cause underlying DataTable will not be marked as changed if you reject the value. Old value will be displayed automatically
private void dataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
var underlyingDataRow = ((DataRowView)dataGridView.Rows[e.RowIndex].DataBoundItem).Row;
if (DoesNotMeetYourCondition)
{
row.RejectChanges();
}
how to do validations for numeric,double and empty values for datagridview in c# windows application.Text values should not be allowed to enter the cells which are numeric or double.how to do it?
You Can validate datagrid view cell like this...
private void dataGridView1_CellValidating(object sender,DataGridViewCellValidatingEventArgs e)
{
// Validate the CompanyName entry by disallowing empty strings.
if (dataGridView1.Columns[e.ColumnIndex].Name == "CompanyName")
{
if (e.FormattedValue == null && String.IsNullOrEmpty(e.FormattedValue.ToString()))
{
dataGridView1.Rows[e.RowIndex].ErrorText =
"Company Name must not be empty";
e.Cancel = true;
}
}
}
void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
// Clear the row error in case the user presses ESC.
dataGridView1.Rows[e.RowIndex].ErrorText = String.Empty;
}
This validates only empty values , if you want validate numericals you can do like this...
I hope it will helps you...
If you'd like to restrict anything but numbers from being entered, you need to handle the EditingControlShowing event on the DataGridView. It can be done like this:
dataGridView.EditingControlShowing = new DataGridViewEditingControlShowingEventHandler (dataGridView_EditingControlShowing);
Then, define your handler:
void dataGridView_EditingControlShowing (object sender, DataGridViewEditingControlShowingEventArgs e)
{
TextBox tx = e.Control as TextBox;
tx.KeyPress += new KeyPressEventHandler (tx_KeyPress_int);
}
Then, define your KeyPress handler, and only handle numeric characters:
void tx_KeyPress_int (object sender, KeyPressEventArgs e)
{
if (!(char.IsNumber (e.KeyChar) || e.KeyChar == '\b'))
{
//is NOT number or is Backspace key
e.Handled = true;
}
}
Adjust to suit your exact needs accordingly (i.e. handle only input on a certain column, etc.)
If you want to validate cell values when user trying to leave cell, you should handle DataGridView.CellValidating event and process cell value there.
If you want to validate value when user typing it, you may handle KeyPress event.
To validate numeric values you may use code like this:
int number = 0;
if(!int.TryParce(cell.Value.ToString(), out number))
{
//report about error input
}
Please read this link.
http://msdn.microsoft.com/en-us/library/aa730881(v=vs.80).aspx
##Edit ,
if you try to use your own custom numeric control,
1. you no need to check any additional validation.
2. It is reusable.
Is there a way to let only certain chars be added to a datagridview cell?
like '1234567890'?
There are two approaches I know of that you can use for this. The first (and I think the best) is to use the CellValidating event on the DataGridView and check if the entered text is numeric.
Here is an example of that which sets the row error value too (with an additional CellEndEdit event handler incase the user cancels out of editing).
private void dataGridView1_CellValidating(object sender,
DataGridViewCellValidatingEventArgs e)
{
string headerText =
dataGridView1.Columns[e.ColumnIndex].HeaderText;
// Abort validation if cell is not in the Age column.
if (!headerText.Equals("Age")) return;
int output;
// Confirm that the cell is an integer.
if (!int.TryParse(e.FormattedValue.ToString(), out output))
{
dataGridView1.Rows[e.RowIndex].ErrorText =
"Age must be numeric";
e.Cancel = true;
}
}
void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
// Clear the row error in case the user presses ESC.
dataGridView1.Rows[e.RowIndex].ErrorText = String.Empty;
}
The second approach is to use the EditingControlShowing event and the attach an event to the cell's KeyPress - I'm not such a fan of this approach since it silently blocks the input of non numeric keys - though I suppose you could give some feedback (like a bell sounding) it just feels like more work compared to the other way.
private void dataGridView1_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
e.Control.KeyPress -= TextboxNumeric_KeyPress;
if ((int)(((System.Windows.Forms.DataGridView)(sender)).CurrentCell.ColumnIndex) == 1)
{
e.Control.KeyPress += TextboxNumeric_KeyPress;
}
}
private void TextboxNumeric_KeyPress(object sender, KeyPressEventArgs e)
{
bool nonNumberEntered = true;
if ((e.KeyChar >= 48 && e.KeyChar <= 57) || e.KeyChar == 8)
{
nonNumberEntered = false;
}
if (nonNumberEntered)
{
// Stop the character from being entered into the control since it is non-numerical.
e.Handled = true;
}
else
{
e.Handled = false;
}
}
One important note with this is be careful to remove the event handler on the control within the editing control showing method. This is important since the DataGridView reuses the same object for each cell of the same type, including across different columns. If you attach an event handler to a control in one textbox column, all the other text box cells in the grid will have the same handler! Also, multiple handlers will be attached, one for each time the control is shown.
The first solution came from this MSDN article. The second came from this blog.
If you would like the datagridview to simply remove the invalid chars for the user, instead of issue an error message, use DataGridView.CellParsing(). This event only fires after you make a cell edit, and allows you to override what was entered.
For example:
private void dataGridView1_CellParsing(object sender, DataGridViewCellParsingEventArgs e)
{
// If this is column 1
if (e.ColumnIndex == 1)
{
// Remove special chars from cell value
e.Value = RemoveSpecialCharacters(e.Value.ToString());
e.ParsingApplied = true;
}
}
For the RemoveSpecialCharacters() method, see this SO question for some excellent methods of removing special chars from a string.