简体   繁体   English

KeyUp事件未在DataGrid上触发

[英]KeyUp event not firing on DataGrid

Can´t figure why it isn't, here's the sample code: 无法理解为什么不是,这是示例代码:

public Form1()
        {
            InitializeComponent();
            //Create DataGrid
            DataGrid dg = new DataGrid();
            dg.Parent = this;
            dg.Location = new Point(10, 10);
            dg.Size = new System.Drawing.Size(300, 200);
            //Create list of people
            List<Person> people = MethodThatFetchesPeople();
            //Bind list
            BindingList<Person> bl_people = new BindingList<Person>(people);
            dg.DataSource = bl_people;
            //Format grid
            dg.TableStyles.Clear();
            DataGridTableStyle dgts = new DataGridTableStyle();
            dgts.MappingName = bl_people.GetType().Name;
            dgts.ReadOnly = true;
            DataGridTextBoxColumn col_name = new DataGridTextBoxColumn();
            col_name.MappingName = "Name";
            col_name.HeaderText = "Name";
            dgts.GridColumnStyles.Add(col_name);
            DataGridTextBoxColumn col_height = new DataGridTextBoxColumn();
            col_height.MappingName = "Height";
            col_height.HeaderText = "Height (cm)";
            dgts.GridColumnStyles.Add(col_height);
            dg.TableStyles.Add(dgts);
            //Subscribe events
            col_name.TextBox.KeyDown += new KeyEventHandler(TextBox_KeyDown);
            col_name.TextBox.KeyUp += new KeyEventHandler(TextBox_KeyUp);
        }

The event handling methods: 事件处理方法:

        void TextBox_KeyUp(object sender, KeyEventArgs e)
        {
            //Do something on keyup
            Debug.WriteLine("Keyup!");
        }

        void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            //Do something on keydown
            Debug.WriteLine("Keydown!");
        }
    }

After pressing on a value from the Name column, that DataGridTextBoxColumn gets the focus. 按下Name列中的值后, DataGridTextBoxColumn获得焦点。 Then whenever I press a key the KeyDown event gets fired but nothing happens for the KeyUp event, even when the KeyDown event isn't subscribed. 然后每当我按下一个键时, KeyDown事件就会被触发,但KeyUp事件没有任何反应,即使未订阅KeyDown事件也是如此。
I really just need the KeyUp event, the KeyDown doesn't fit my purpose. 我真的只需要KeyUp事件,KeyDown不符合我的目的。 And I can't just switch to the DataGridView as this code will be used with the compact framework :( 我不能只是切换到DataGridView,因为此代码将与紧凑框架一起使用:(
How can I solve this? 我怎么解决这个问题?

I have seen this happen specifically on Windows Forms / desktop application, but posting here in case it also holds true on mobile. 我已经看到这种情况特别发生在Windows窗体/桌面应用程序上,但在此处发布,以防它在移动设备上也适用。

DataGrid control has a habit of "swallowing" certain keyboard events. DataGrid控件习惯于“吞咽”某些键盘事件。 It processes them internally (I believe they are processed by the individual grid cells) and they will not "bubble up" to other controls because the event has already been consumed. 它在内部处理它们(我相信它们由各个网格单元处理)并且它们不会“冒泡”到其他控件,因为事件已被消耗。

There are two different ways to do this. 有两种不同的方法可以做到这一点。 Basically you need to set up the form to intercept the event before it hits the DataGrid, then pre-process and decide if you also want to pass the event to the DataGrid. 基本上,您需要设置表单以在事件到达DataGrid之前拦截事件,然后预处理并决定是否还要将事件传递给DataGrid。

To create a "Universal Filter" inside your application do the following. 要在应用程序内创建“通用过滤器”,请执行以下操作。 You would do this if you are following a dispatcher pattern and potentially need to route the key stroke to one of many different controls: 如果您遵循调度程序模式并且可能需要将键击路由到许多不同控件之一,则可以执行此操作:

In your Form's constructor: 在Form的构造函数中:

this.KeyPreview = true;
Application.AddMessageFilter(this);

Override this method in your form. 在表单中覆盖此方法。 If this method returns "true" the event will be consumed and will not be dispatched to any other controls. 如果此方法返回“true”,则将消耗该事件,并且不会将该事件分派给任何其他控件。 If this method returns "false" the event will bubble through all the controls as normal. 如果此方法返回“false”,则事件将正常地通过所有控件。

    // This is the ONLY way to prevent buttons, checkboxes, and datagrids from processing the UP and DOWN arrows
    const int WM_KEYDOWN       = 0x100;
    const int WM_KEYUP         = 0x101;
    public bool PreFilterMessage(ref Message m)
    {
        try
        {

            if (m.Msg == WM_KEYDOWN)
                // handle event here and return true
            else if (m.Msg == WM_KEYUP)
                // handle event here and return true
            }
        }
        catch
        {
            return false;
        }

    return false;
    }

I wrote / figured all this out about 10 years ago so maybe there are other / better ways to do this, but this worked for me and I didn't have to create custom implementations of any controls to make it work. 我在大约10年前编写/计算了所有这些,所以也许有其他/更好的方法来做到这一点,但这对我有用,我不必创建任何控件的自定义实现来使其工作。


Another technique I found in an MSDN article. 我在MSDN文章中找到的另一种技术。 It is written for VB but should translate pretty easily to C#: 它是为VB编写的,但应该很容易翻译成C#:

https://support2.microsoft.com/default.aspx?scid=kb;en-us;320583&Product=vbNET https://support2.microsoft.com/default.aspx?scid=kb;en-us;320583&Product=vbNET

The basic premise here is to subclass the DataGrid and override the ProcessCmdKey method. 这里的基本前提是ProcessCmdKey DataGrid并覆盖ProcessCmdKey方法。

This MSDN Article suggests keyboard event handling in CF is not easy, but it may offer a solution. 这篇MSDN文章建议CF中的键盘事件处理并不容易,但它可能提供一个解决方案。 I did not read it all. 我没有读完这一切。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM