Click here to Skip to main content
15,914,500 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hi all
I wanna override datagridview_keypress method , but I have following error :

no suitable method for override

Code:
C#
private void dataGridView2_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
        {
if (dataGridView2.CurrentCell.ColumnIndex == 5 || dataGridView2.CurrentCell.ColumnIndex == 6 || dataGridView2.CurrentCell.ColumnIndex == 7)
{
                e.Control.KeyPress += new KeyPressEventHandler(dataGridView2_KeyPress);
            }
            if (dataGridView2.CurrentCell.ColumnIndex == 1 || dataGridView2.CurrentCell.ColumnIndex == 0 || dataGridView2.CurrentCell.ColumnIndex == 2 || dataGridView2.CurrentCell.ColumnIndex == 4)
            {
                e.Control.KeyPress += new KeyPressEventHandler(dataGridView2_KeyPress);
            }
        }

        protected override void dataGridView2_KeyPress(KeyPressEventArgs e)
        {
            if (!char.IsNumber(e.KeyChar))
            {
                e.Handled = true;
            }
            if (char.IsControl(e.KeyChar))
            {
                e.Handled = false;
            }
        }
        private void dataGridView2_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (char.IsNumber(e.KeyChar))
            {
                e.Handled = true;
            }
            if (char.IsControl(e.KeyChar))
            {
                e.Handled = false;
            }
        }
Posted
Comments
Sergey Alexandrovich Kryukov 14-May-15 17:44pm    
Where did you find such virtual method? If then method is called dataGridView2_KeyPress and you did not write it, it is auto-generated and not virtual. By the way, you should never use such method names...
—SA

It looks like you tried to implement the DataGridView.OnKeyPress(..)-overriding method as a method of the Form in which you use the DataGridView.

If you want to override ANY method of a class, you have to create a subclass of it:

1) Add a new class-file to your project (name it like your custom DataGridView-class should be named).
2) Add a using-directive for the namespace "System.Windows.Forms".
3) Change the auto-generated class-stub to derive from DataGridView.
4) Override OnKeyPress(..) (Place the cursor into the body of the class, type just "ov" and press space and you'll get an IntelliSense-popup to assist you.)
5) Implement your custom code in the overridden method and maybe other required methods.

Something like this would be the bare minimum (which doesn't actually add anything to a regular DataGridView):
C#
using System.Windows.Forms;

namespace MyProject
{
    public class MyDataGridView : DataGridView
    {
        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            base.OnKeyPress(e);
        }
    }
}


To be able to place a "MyDataGridView" on your Form do this:
Go to Tools > Options > Windows Forms Designer > General
..and ensure that the option "AutoToolboxPopulate" is set to true. Then rebuild your solution. "MyDataGridView" should then show up in the Toolbox under a category that has the same name as your project. If it doesn't show up, close and re-open Visual Studio.
 
Share this answer
 
v4
Comments
Sergey Alexandrovich Kryukov 14-May-15 17:45pm    
5ed, but... Do you understand why I'm afraid that it won't help the enquirer much? :-)
—SA
Sascha Lefèvre 14-May-15 17:54pm    
Thank you, Sergey. And fixed, I guess :-)
Sergey Alexandrovich Kryukov 14-May-15 17:58pm    
You can see the confirmation of my concern in questions below.
The problem is not the inability to override something; the problem is the lack of understanding of both OOP and events.
—SA
bernova 14-May-15 17:56pm    
where I should Define Subclass?
bernova 14-May-15 17:58pm    
Dear Surgey
when I use just dataGridView2_keypress function , that run correctly.
example :


private void dataGridView2_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
if (dataGridView2.CurrentCell.ColumnIndex == 5 || dataGridView2.CurrentCell.ColumnIndex == 6 || dataGridView2.CurrentCell.ColumnIndex == 7)
{
e.Control.KeyPress += new KeyPressEventHandler(dataGridView2_KeyPress);
}

}


private void dataGridView2_KeyPress(object sender, KeyPressEventArgs e)
{
if (!char.IsNumber(e.KeyChar))
{
e.Handled = true;
}
if (char.IsControl(e.KeyChar))
{
e.Handled = false;
}
}
bernova asked:

Dear Sergey, when I use just one of keypress function, that run correctly?
You don't understand.

There are no "keypress functions". There are events: KeyPress, KeyDown, KeyUp, PreviewKeyDown. Events can be handled by adding your own methods to the invocation list of some event instances. Don't mix 3 things: 1) events as something which happens; 2) events as delegate types used in events; 2) events as instanced, members of some class invoking the event. Also, it's good not to mix up all these meanings of events with event handlers, which are delegate instances. Alternatively, you override the virtual methods such as OnKeyPress, OnPreviewKeyDown, and so on. These On* methods can be overridden to handle corresponding events (in the sense #1) without adding event handlers.

Please see:
https://msdn.microsoft.com/en-us/library/edzehd2t%28v=vs.110%29.aspx[^],
https://msdn.microsoft.com/en-us/library/system.windows.forms.control_events%28v=vs.110%29.aspx[^],
https://msdn.microsoft.com/en-us/library/system.windows.forms.control_methods%28v=vs.110%29.aspx[^].

See also:
http://en.wikipedia.org/wiki/Object-oriented_programming[^],
http://en.wikipedia.org/wiki/Virtual_function[^],
http://en.wikipedia.org/wiki/Dynamic_dispatch[^].

Even your whole idea "run correctly" is wrong. You should not try to "run correctly" or incorrectly anything, not yet. First, you need to understand what is "correctly", and a lot more: the idea of how things work. Unfortunately, right now you have no clue, and trial-and-error attempts cannot help you; and neither can help the "how to do it" recipes. You need to get the ideas.

[EDIT #1]

To achieve filtering of key press events, you could write
C#
using System.Windows.Forms;

namespace MyProject
{
    public partial class MyTextBox : TextBox {
        protected override void OnKeyPress(KeyPressEventArgs e) {
            e.Handled = !char.IsNumber(e.KeyChar);
            // no need to write "if" and assign e.Handled = false
            // but I would also add
            if (e.KeyChar == (char)8)
                e.Handled = false;
            // of course, you should better combine these two checks
            // for 8 and for !char; use Boolean operators
        }
    }
}

I answered to your code request, but I also need to explain the deal with 8: this is backspace which you need to allow.

Sorry that you are getting upset with my "you don't understand", but apparently you also don't quite understand how to work with Boolean expressions and "if".

Now, this is not what you need. DataGridView is not a text box. You probably need to do the same for the text box which is the grid cell. You need to do it to the text box, not to the grid view itself.

This is how:

First of all, you need to handle the event DataGridView.EditingControlShowing:
C#
public class MyDataGridView : DataGridView {

    public MyDataGridView() {
        //...
        this.EditingControlShowing += (sender, eventArgs) => {
            if (eventArgs.Control.Tag == null) // [EDIT #2]
                eventArgs.Control.KeyPress +=
                    (editorSender, editorEventArgs) => {
                        bool isValid = char.IsDigit(editorEventArgs.KeyChar);
                        isValid != editorEventArgs.KeyChar == (char)8;
                        editorEventArgs.Handled = !isValid;
                    }
            eventArgs.Control.Tag = true; // prevent unwanted
                                          // extra subscribing
                                          // [EDIT #2]
        };
    }

    // ...

} //class MyDataGridView

Can you see how tricky is that? You add and event handler each time the event EditingControlShowing is invoked; you add it to the editor you obtain from this first event. Then you handle each key press to filter out non-digit, but not backspace.

Also, this code is written in assumption that all your cells are of the type System.Windows.Forms.DataGridViewTextBoxCell. So you also need to excluded the cases when the control is of some different type. You can simply check up the runtime type of the currently selected cell.

Please see:
https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.editingcontrolshowing%28v=vs.110%29.aspx[^],
https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridvieweditingcontrolshowingeventargs%28v=vs.110%29.aspx[^],
https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridvieweditingcontrolshowingeventargs.control%28v=vs.110%29.aspx[^].

[EDIT #2]

Sascha Lefèvre found a bug in my original code, a memory leak. Please see our discussion in comments. I mistakenly assumed that new instance of the editor eventArgs.Control is created each time the editing is started.

Sascha checked up in the code sample he provided that the same instance of the editor is reused. I can confirm it; moreover, in the tests I executed, only one instance per DataGridView instance was created. Therefore, my code would add a new handler to the invocation list of the event instance eventArgs.Control.KeyPress again and again. After I realized that, I added a simple guard based on the Tag property which fixes the problem. The leak problem is fixed; the correspondent lines are commented with "[EDIT #2]" in the code sample.

Note that this fix is reliable (FCL controls guarantee that this property is never touched by the libraries themselves) and is not making any assumptions on identities of the controls. The fix based on unsubscribed methods would be much more complicated, especially if it is made making no assumption on controls' identity. Such assumptions should not be made, because they are not documented, so the internal implementation of DataGridView could be changed at any version. Basically, it would require having an external collection of control instances ("subscribed controls"), and each subscription would need to check for the presence in the subscribed control collection.

Moreover, unsubscribe operation would (-=) require named, not anonymous methods, which is always worse; anonymous methods do not allow calling in any code except the '+=' operand, which provides better encapsulation.

One more issue would have to be resolved if you needed two or more "sorts of cells", with different character filtering rules. If this is the case, I would strongly recommend only one KeyPress handler working differently for different kinds of cells, through some "if" check inside the handler.

—SA
 
Share this answer
 
v9
Comments
bernova 14-May-15 18:35pm    
ok. that's so very good sites.

"You don't understand" Is bad Sentence.
I know your Purpose. because I use the function word instead of event.
I know what is different between event and function ... if don't know , can not write part of code that run correctly?!!

you are master.

thanks a lot.
best regards
Sergey Alexandrovich Kryukov 14-May-15 18:57pm    
I'm sorry that you don't like my sentence. But 1) there is nothing offensive in it; 2) I still have all the reasons to think that you don't understand how this part works, otherwise you would never write "override datagridview_keypress method". And this is not about the "word", this is about understanding.

Now, the correct code, one of possible variants, is written in Solution 1. But now, this is the point: it does nothing. It is written the way logically equivalent to having no overridden OnKeyPress. This is always the key when you call the base method in implementation, such as base.OnKeyPress. To add some functionality, you have to add or replace the implementation with what you want.

—SA
Sergey Alexandrovich Kryukov 14-May-15 19:32pm    
Please see the solution in my updated answer, after [EDIT].
—SA
bernova 15-May-15 6:55am    
thanks a lot.
bernova 15-May-15 7:04am    
In the accounting software that we designed , for the Convenience , the user edit her information in the datagridview and press enter. indeed the user(customer) request to us , now we validating datagridview cells.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900