简体   繁体   中英

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. 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.
I really just need the KeyUp event, the KeyDown doesn't fit my purpose. And I can't just switch to the DataGridView as this code will be used with the compact framework :(
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.

DataGrid control has a habit of "swallowing" certain keyboard events. 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.

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:

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. If this method returns "false" the event will bubble through all the controls as normal.

    // 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.


Another technique I found in an MSDN article. It is written for VB but should translate pretty easily to C#:

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.

This MSDN Article suggests keyboard event handling in CF is not easy, but it may offer a solution. I did not read it all.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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