c# - KeyUp 事件未在 DataGrid 上触发

标签 c# events datagrid compact-framework

无法理解为什么不是,这里是示例代码:

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

事件处理方法:

        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!");
        }
    }

按下 Name 列中的值后,DataGridTextBoxColumn 获得焦点。 然后,每当我按下一个键时,KeyDown 事件就会被触发,但 KeyUp 事件没有任何反应,即使未订阅 KeyDown 事件也是如此。
我真的只需要 KeyUp 事件,KeyDown 不符合我的目的。而且我不能只切换到 DataGridView,因为此代码将与紧凑型框架一起使用:(
我该如何解决这个问题?

最佳答案

我已经看到这种情况特别发生在 Windows 窗体/桌面应用程序上,但在这里发帖以防它在移动设备上也适用。

DataGrid 控件有“吞噬”某些键盘事件的习惯。它在内部处理它们(我相信它们是由各个网格单元处理的)并且它们不会“冒泡”到其他控件,因为事件已经被消耗。

有两种不同的方法可以做到这一点。基本上,您需要设置表单以在事件到达 DataGrid 之前拦截它,然后进行预处理并决定是否还想将事件传递给 DataGrid。

要在您的应用程序中创建一个“通用过滤器”,请执行以下操作。如果您遵循调度程序模式并且可能需要将击键路由到许多不同控件之一,则可以这样做:

在表单的构造函数中:

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

在您的表单中覆盖此方法。如果此方法返回“true”,则事件将被使用并且不会被分派(dispatch)给任何其他控件。如果此方法返回“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;
    }

我在大约 10 年前写了/想出了所有这些,所以也许有其他/更好的方法来做到这一点,但这对我有用,我不必创建任何控件的自定义实现来使其工作。


我在 MSDN 文章中找到的另一种技术。它是为 VB 编写的,但应该很容易转换为 C#:

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

这里的基本前提是继承 DataGrid 并覆盖 ProcessCmdKey 方法。

关于c# - KeyUp 事件未在 DataGrid 上触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29098478/

相关文章:

c# - 保证一个类只能被实例化它的线程使用

c# - OmniSharp.MSBuild.ProjectManager 尝试更新未加载的项目 :

java - 自定义 JavaFX 事件

WPF DataGrid - 创建一个新的自定义列

wpf - 在 DataGridTextColumn 中为 TextBlock 创建样式

C# 如何以编程方式指定列作为主索引

javascript - 通过 `appendChild` 添加到 DOM 树的元素不会在 IE6/7 中显示(也 `onclick` 事件未触发)

c# - 委托(delegate)与事件

c# - 如何判断 DataGrid 的哪一行被单击?

c# - Shared Xamarin.Forms - 命名空间中不存在类型或命名空间名称 'App'