views:

1406

answers:

1

I have a DataGridView (WinForms) in which I have defined a custom EditingControl derived from DataGridViewTextBoxEditingControl that only allows numeric characters.

I need to raise CellValueChanged event on the DataGridView each time the user press a key, but the default behaviour is to raise the event only when edition has been completed.

How can I raise the event each time a key is pressed?

public class DataGridViewNumericTextBoxEditingControl : DataGridViewTextBoxEditingControl
{
    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        e.Handled = Char.IsLetter(e.KeyChar);
        if (!e.Handled)
            RaiseDataGridViewCellValueChanged(); // <-- Any way?
    }
}

Update:

I've found a workaround, but I'm not sure it's a good solution:

public class DataGridViewNumericTextBoxEditingControl : DataGridViewTextBoxEditingControl
{
    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        e.Handled = Char.IsLetter(e.KeyChar);
        if (!e.Handled)
        {
            EditingControlDataGridView.EndEdit();
            EditingControlDataGridView.BeginEdit(false);
        }
    }
}
+1  A: 

What is the goal here? It appears you are attempting to create a keyboard mask, where any non confirming character raises an alert? If so, you may find happiness in the DataGridView by adding a MaskedTextBoxColumn. A MaskedTextBoxColumn controls the input in a much more reasonable way than forcing edit commits.

See here for code that shows how to use it: http://msdn.microsoft.com/en-us/library/ms180996.aspx

According to your updated criteria in the comments, it sounds like your solution is probably about as good as it will get. Realize, however, that it is very easy to get into infinite event loops when you have other controls updating on another based on keyboard events. You are probably best served to have a single delegate on the form that handles all of the events as it can prevent infinite loops of event triggers by discarding spurious events them based on state.

Effectively this would be using the Model View Presenter pattern, where your delegate acts as the presenter and manages the traffic on your View (your UI).

Doing this, you can even move the Presenter logic into a new class that you then data bind to, allowing you complete control over the UI from one logical construct, rather than a hodgepodge of event handlers.

Godeke
I'm trying to detect when the cell text has changed without waiting for focus to leave the cell.
Juanma
I guess I should rephrase: if you are attempting to detect cell changes, responding to event like OnKeyPress is fine. My point is... perhaps you should use a control *designed* for masking input to numeric only *intrinsically*.
Godeke
I agree with that, but the real problem is that I need to update other controls in the screen as soon as the user press a key (i.e. recalculate some totals shown in labels)
Juanma
OK: the "that only allows numeric characters" part is a red herring. This sounds like a *very* bad idea to be in a data grid and doing real time updates unless you have some very unusual design requirements: the ability to back out of an edit is lost.
Godeke
Thinking more, I believe you might want to look into the Model View Presenter pattern. More in the edited answer.
Godeke