Filtering out input of data in the
DataGridViewCell
is really easy. Unfortunately, you are not even trying to do it in your code. It's absolutely unclear how can your code work even for validation. It cannot.
So, let's start with filtering. First, you need to obtain the control to handle. The edit control is created each time you enter the editing mode. So, first, you need to handle the event
DataGridView.EditingControlShowing
. It will give you the reference to editing control through the event arguments parameter, its property
Control
. Please see:
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.editingcontrolshowing%28v=vs.110%29.aspx[
^],
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridvieweditingcontrolshowingeventargs%28v=vs.110%29.aspx[
^],
http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridvieweditingcontrolshowingeventargs.control(v=vs.110).aspx[
^].
After this is done, you obtain this control reference of the type
Control
. As with all controls, you can filter out some input characters by handling the event
Control.KeyPress
. This control is
cancellable, you can avoid entering some character by assigning true to the properly
Cancel
of the event arguments parameter. This is explained here, pay attention for the code sample:
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.keypress%28v=vs.110%29.aspx[
^].
In the simplest possible case, just for demonstration, let's assume you have to do it will all the cells of some instance of the grid:
DataGridView myGridView =
myGridView.EditingControlShowing += (sender, eventArgs) => {
Control control = eventArgs.Control;
control.KeyPress += (keyPressSender, keyPressEventArgs => {
keyPressEventArgs = !goodDoubleCharacter(keyPressEventArgs.KeyChar);
}
}
static bool goodDoubleCharacter(char testCharacter) {
return
}
Simple, isn't it? Now you can allow decimal point, all digits, optionally + or −, optionally 'E' or 'e', for scientific notation, and, important,
(char)8
, which is the backspace, by some weird historical reason also processed as character and not as the virtual key, so it will be filtered out if you forget it.
Now, most important part of the answer:
don't even try to to reject '.' unless its in combination with a numeric value"! You would only greatly confuse the user, create enormous inconveniences (let's say, drive the users crazy) and still won't be able to guarantee valid input. Criteria like this never make some sense. You should later just validate the input.
I'll explain. Let's say, you want to allow only one '.' and only between two integers. Now imagine how the user enters the value. The user enters one digit then, '.', then… wait a second! input is already invalid; there is not trailing character. Ah, you want to allow '.' at the end during input? But there is no "during input". The user can enter digits first, and only later insert '.', but a reasonable user won't do it.
The users expect that they are allowed to enter some invalid string at first and make it valid only by the moment when the entered data is about to be used.
So, my advice would be: validate data only when the data is about to be used. Many validate data item by item, when a user shifts the control focus to other control (not applicable to a single grid view with editing cells). Even though in simple cases it can be useful, it general case this is simply impossible, because some elements of data may depend on each other, they are valid or not not separately, but all together, only. And this is applicable to a set of cells on a grid view, too.
So, how to validate? Of course, but by checking where '.' is. :-)
First, you need to check up if the string is valid as the representation of the floating-point value (for example, double). This is how:
DataGridViewCell cell =
string value = (string)cell.Value;
double doubleValue;
bool valid = double.Parse(value, out doubleValue);
Note that you also obtained the double value, for free. You can use it for further validation, say, to validate that the value falls in some valid range.
Sorry that the code is in C#. I hope it is clear enough to give you the idea. In VB.NET, everything will be pretty much the same. I uses anonymous event handlers (highly recommended), and similar VB.NET syntax is explained here:
http://visualstudiomagazine.com/articles/2011/11/28/integrating-lambda-expressions-and-events.aspx[
^].
Anyway, you can consult appropriate MSDN pages on each type/method used.
—SA