Member 11827207 wrote:
if I am able to make an event fire, I can check if the entered value is number.
Even I can fetch some corresponding data from database.
Thank you for the clarification; you should have explained that in detail in first place.
Unfortunately, you formally accepted totally bad Solution 1. Never do such things, first of all, never do stupid things like hard-coding "ColumnText" and the like. Besides, it does not provided any solution at all.
You can do two things: 1) capture the entering event of the in-place editing control and filter out all entered characters except digits and backspace (which is interpreted as character with code point 8); 2) when editing mode is ended, validate all entered text. In my solution, you need to handle three events of you grid view plus
KeyPress
event of the in-place control you can extract from the event
DataGridView.EditingControlShowing
. In my code sample, the event
DataGridView.CellBeginEdit
is used exclusively to locate the currently editing cell via storing coordinates in
currentRow, currentColumn
. You my need it just because you want to apply the filtering of validation not for all cells to be edited, but only to some of them. The cells can be discriminated by columns, or both column and row.
The code shown below could be added anywhere at the end of the form constructor. Note that I declared
editControl
,
currentRow
as
currentColumn
as local variable; the are accessed from the event handler via the
closure mechanism (
Closure (computer programming)[
^]).
Control editControl = null;
int currentRow, currentColumn;
myGridView.EditingControlShowing += (sender, eventInstance) => {
if (!NeedsFiltering(currentRow, currentColumn)) return
if (eventInstance.Control != editControl) {
editControl = eventInstance.Control;
editControl.KeyPress += (editorSender, editorEvent) => {
editorEvent.Handled =
!(char.IsDigit(editorEvent.KeyChar)
|| editorEvent.KeyChar == (char)8);
};
}
};
myGridView.CellBeginEdit += (sender, eventInstance) => {
currentColumn = eventInstance.ColumnIndex;
currentRow = eventInstance.RowIndex;
};
myGridView.CellEndEdit += (sender, eventInstance) => {
ValidateCell(eventInstance.ColumnIndex, eventInstance.RowIndex);
};
Here, you have two add two methods:
NeedsFiltering(int, int)
used to validate that the cell in question is relevant to the task of integer editing, and your validation method of the just edited cell content,
ValidateCell(int, int)
.
The schema of validation algorithm:
First, you get a cell by its cow/column indices; for the cell, extract its value by using it's property
Value
, typecast it to string and validate string value.
For numeric validation, you use
int.TryParse
(or the integer type you need). Despite the fact that you already made sure the user entered only digits, it still may not parse successfully. Say, no digits or too many digits. So, this method should return true for valid integer. In this cases, integer value is returned in the second parameter, and you can check up if the integer value is valid.
There is one quite delicate point in the solution: when you add the filtering event handler, the grid view does not create new instance of the in-place editor each time. On second time, it can provide previously created control instance, it it is suitable for new editing session; this is what really happened. That's why I check up that it's the "same editor as before" via comparison with the variable
editControl
. If not this check, it would create a very subliminal
memory leak, because the same event handler would be added to the same control again and again. This is one of the rare cases when a small mistake can create a memory leak in managed memory. (Many think that managed memory leak is impossible, but this is not true.)
My solution is fully tested, be sure about that.
[EDIT]
Now, about the SQL injection issue raised by Richard Deeming in his comments to the question. He is perfectly right.
Your approach is wrong from the very beginning. The query composed by concatenation with strings taken from UI. Not only repeated string concatenation is inefficient (because strings are
immutable; do I have to explain why it makes repeated concatenation bad?), but there is way more important issue: it opens the doors to a well-known exploit called
SQL injection.
This is how it works:
http://xkcd.com/327.
Are you getting the idea? The string taken from a control can be anything, including… a fragment of SQL code.
What to do? Just read about this problem and the main remedy:
parametrized statements:
http://en.wikipedia.org/wiki/SQL_injection.
With ADO.NET, use this:
http://msdn.microsoft.com/en-us/library/ff648339.aspx.
Please see my past answers for some more detail:
EROR IN UPATE in com.ExecuteNonQuery();,
hi name is not displaying in name?.
—SA