在 C# Win-Forms 的 ListView 项目编辑中没有击中 KeyEvent

No KeyEvent is hitting in ListView Item Edit in C# Win-Forms

我正在开发一个 Win-Forms 应用程序,有一个显示了一些项目的列表视图,需要编辑项目的标签。 所以启用 LabelEdit 属性 为真,并调用

listView1.SelectedItems[0].BeginEdit();

单击上下文菜单项。一切正常。

现在我需要验证用户在项目名称中输入的字符, 比如名字中不允许有特殊字符,所以在列表视图中注册了keyDown event,但是在标签编辑模式下没有被击中,我尝试了所有其他按键事件,但是none被击中了。

一种解决方案是在

中进行验证
private void listView1_AfterLabelEdit(object sender, LabelEditEventArgs e)
{
    // Validation code goes here
}

但我不想这样做,我想在用户输入无效字符时显示工具提示

谁能告诉我使用哪个事件?? 如有任何帮助,我们将不胜感激。

你试过 Form.KeyPreview 了吗? https://msdn.microsoft.com/en-us/library/system.windows.forms.form.keypreview(v=vs.100).aspx

你可以设置一个 bool 变量来知道你正在编辑标签,当它是真的时,你继续对 Form.Keydown

执行验证

ListView 在用户开始编辑标签时动态创建一个 TextBox 控件。此控件未被 Winforms 包装,并且不与 OnBefore/AfterLabelEdit 事件之外的父事件交互。

这可以解决。 LVM_GETEDITCONTROL 消息允许您获取该文本框的句柄。然后 NativeWindow class 可以子 class 控件,这样您就可以拦截它的消息。点赞你感兴趣的键盘留言。

这里有一个例子,它将LabelKeyPress事件添加到ListView。您可以为其编写事件处理程序并将 e.Handled 属性 设置为 true 以防止使用按键。向您的项目添加一个新的 class 并粘贴下面的代码。编译。从工具箱顶部拖放新控件,替换原来的 ListView。

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;

class ListViewEx : ListView {
    public event KeyEventHandler LabelKeyDown = delegate { };
    public event KeyEventHandler LabelKeyUp = delegate { };
    public event KeyPressEventHandler LabelKeyPress = delegate { };
    private LabelTextBox Label;

    public ListViewEx() {
        Label = new LabelTextBox(this);
    }
    protected void OnLabelKeyDown(KeyEventArgs e) { LabelKeyDown(this, e); }
    protected void OnLabelKeyUp(KeyEventArgs e) { LabelKeyUp(this, e); }
    protected void OnLabelKeyPress(KeyPressEventArgs e) { LabelKeyPress(this, e); }

    protected override void OnBeforeLabelEdit(LabelEditEventArgs e) {
        const int LVM_GETEDITCONTROL = 0x1000 + 24;
        var hdl = SendMessage(this.Handle, LVM_GETEDITCONTROL, IntPtr.Zero, IntPtr.Zero);
        Label.AssignHandle(hdl);
        base.OnBeforeLabelEdit(e);
    }
    protected override void OnAfterLabelEdit(LabelEditEventArgs e) {
        Label.ReleaseHandle();
        base.OnAfterLabelEdit(e);
    }

    private class LabelTextBox : NativeWindow {
        private ListViewEx Parent;
        public LabelTextBox(ListViewEx parent) { this.Parent = parent; }

        protected override void WndProc(ref Message m) {
            switch (m.Msg) {
                case 0x100:
                    var args = new KeyEventArgs((Keys)m.WParam.ToInt32());
                    Parent.OnLabelKeyDown(args);
                    if (args.Handled) return;
                    break;
                case 0x101:
                    var args2 = new KeyEventArgs((Keys)m.WParam.ToInt32());
                    Parent.OnLabelKeyUp(args2);
                    break;
                case 0x102:
                    var args3 = new KeyPressEventArgs((char)m.WParam.ToInt32());
                    Parent.OnLabelKeyPress(args3);
                    if (args3.Handled) return;
                    break;
            }
            base.WndProc(ref m);
        }
    }

    [DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
}