覆盖datagridview_keypress方法 [英] Override datagridview_keypress method

查看:81
本文介绍了覆盖datagridview_keypress方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好

我想覆盖datagridview_keypress方法,但我有以下错误:



没有合适的覆盖方法



代码:

Hi all
I wanna override datagridview_keypress method , but I have following error :

no suitable method for override

Code:

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;
            }
        }

推荐答案

看起来你试图实现DataGridView.OnKeyPress(..) - 覆盖方法作为使用DataGridView的Form的方法。



如果要覆盖类的任何方法,则必须创建它的子类:



1)在项目中添加一个新的类文件(名称就像你的自定义DataGridView类一样命名)。

2)为名称空间System.Windows.Forms添加using指令。

3)将自动生成的类存根更改为从DataGridView派生。

4 )覆盖OnKeyPress(..)(将光标放入类的主体,只键入ov并按空格键,您将获得一个IntelliSense弹出窗口来帮助您。)

5)在重写方法中实现您的自定义代码,也许还有其他必需的方法。



像这样的东西是最低限度的(实际上并没有添加一个你需要一个常规的DataGridView):

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):
using System.Windows.Forms;

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





能够在表单上放置MyDataGridView这样做:

转到工具>选项> Windows窗体设计器>一般

..并确保选项AutoToolboxPopulate设置为true。然后重建您的解决方案。然后,MyDataGridView应显示在工具箱中与您的项目同名的类别下。如果它没有显示,请关闭并重新打开Visual Studio。



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.


bernova问:



亲爱的谢尔盖,当我只使用其中一个按键功能时,运行正常?


Dear Sergey, when I use just one of keypress function, that run correctly?

你不明白。



没有按键功能。有事件: KeyPress KeyDown KeyUp PreviewKeyDown 。可以通过将您自己的方法添加到某些事件实例的调用列表来处理事件。不要混合3件事:1)事件发生的事情; 2)事件作为事件中使用的委托类型; 2)事件为instanced,某些类的成员调用该事件。此外,最好不要将事件的所有这些含义与作为委托实例的事件处理程序混淆。或者,您可以覆盖虚拟方法,例如 OnKeyPress OnPreviewKeyDown ,依此类推。这些 On * 方法可以被覆盖以处理相应的事件(在某种意义上#1),而无需添加事件处理程序。



请参阅:

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.contr ol_methods%28v = vs.110%29.aspx [ ^ ]。



参见:

http://en.wikipedia.org/wiki/Object-oriented_programming [ ^ ],

http://en.wikipedia.org/wiki/Virtual_function [ ^ ],

http:// en .wikipedia.org / wiki / Dynamic_dispatch [ ^ ] 。



即使你的整个想法正确运行也是错误的。你不应该尝试正确运行或错误的任何东西,还没有。首先,你需要了解什么是正确,还有更多:理解事物的运作方式。不幸的是,现在你没有任何线索,尝试和错误的尝试无法帮助你;并且都不能帮助如何做食谱。你需要得到这些想法。







实现按键过滤事件,您可以使用 System.Windows.Forms编写

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.



To achieve filtering of key press events, you could write

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
        }
    }
}



我回答了你的代码请求,但我还需要解释与8的交易:这是你需要允许的退格。



抱歉你对我你不理解感到不满,但显然你也是我不太明白如何使用布尔表达式和if。



现在,这不是你需要的 DataGridView 不是文本框。您可能需要对文本框(网格单元格)执行相同的操作。你需要在文本框中进行,而不是对网格视图本身。



这是如何:



首先,您需要处理事件 DataGridView.EditingControlShowing


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:

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



你能看出这有多棘手吗?每次调用 EditingControlShowing 事件时,都要添加事件处理程序;您将它添加到您从第一个事件中获得的编辑器中。然后你按下每个按键来过滤掉非数字,但不是退格。



此外,这段代码的编写假设你的所有单元格都是 System.Windows.Forms.DataGridViewTextBoxCell 。因此,当控件属于某种不同类型时,您还需要排除这些情况。您只需检查当前所选单元格的运行时类型



请参阅:

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 [ ^ ]。







SaschaLefèvre在原始代码中发现了一个错误,内存泄漏。请在评论中查看我们的讨论。 我错误地假设每次编辑开始时都会创建编辑器 eventArgs.Control 的新实例。



Sascha在他提供的代码示例中检查了重用的编辑器实例。我可以确认一下;此外,在我执行的测试中,每个 DataGridView 实例只创建了一个实例。因此,我的代码会一次又一次地向事件实例 eventArgs.Control.KeyPress 的调用列表中添加一个新的处理程序。在我意识到这一点之后,我添加了一个基于 Tag 属性的简单防护来修复问题。 泄漏问题已修复;相应的行在代码示例中注释为。



请注意,此修复是可靠的(FCL控件保证此属性永远不会被触及由图书馆自己)并没有对控件的身份做出任何假设。基于未订阅方法的修复将会复杂得多,特别是如果不对控件的身份做出假设。不应该做出这样的假设,因为它们没有记录,因此可以在任何版本中更改 DataGridView 的内部实现。基本上,它需要一个外部控件实例集合(订阅控件),每个订阅都需要检查订阅控件集合中是否存在。



此外,取消订阅操作会( - =)需要命名,而不是匿名方法,这总是更糟;匿名方法不允许调用除'+ ='操作数之外的任何代码,这提供了更好的封装。



如果你需要两个问题,还有一个问题需要解决或更多类型的单元格,具有不同的字符过滤规则。如果是这种情况,我强烈建议只有一个 KeyPress 处理程序对不同类型的单元格有不同的工作方式,通过一些if检查 inside 处理程序。



-SA


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[^].



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 "" 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


这篇关于覆盖datagridview_keypress方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆