为什么 PropertyGrid 没有触发键盘/鼠标事件?

9
为什么这个函数从来没有被调用?
        propertyGrid.KeyDown += new KeyEventHandler(propertyGrid_KeyDown);

        private void propertyGrid_KeyDown(object sender, KeyEventArgs e)
        {
           PoorLittleMethod(); //Never gets called
        }

这似乎也适用于鼠标事件。

我在一些论坛上读到,PGrid在引发此类事件时很棘手,因为它从Control继承了它们,但实际上并没有引发它们。这是真的吗?如果是,如何规避这种情况?

编辑1:
由于这似乎是“常规”的问题,我认为微软应该在propertyGrid类的MSDN参考文献中明确说明这一点,并将事件“原样”留下来,就好像它们可以使用一样,但事实并非如此。像这样棘手的问题通常至少会在参考文献内部的“备注”中进行指定。

编辑2:
我目前正在编写一个解决方法,很快就会发布。


关于您的编辑:最奇怪的是,MSDN实际上在参考页面上有一个PropertyGrid.KeyDown事件_示例_和_示例代码_。 - Grant Thomas
在这种情况下,我确实错过了什么,因为在我的情况下,那段代码从未被调用,当我尝试复制它时。 - Mehdi LAMRANI
3个回答

2

PropertyGridKeyDown属性被标记为Browsable(false)——我们可以得出结论,它本身并不支持该属性,但实际上是由其继承层次结构产生的副作用。

有趣的是,它的EditorBrowsable属性(也是设计器指示器,用于智能感知等)被设置为EditorBrowsableState.Advanced——如果前面的推测成立,我们应该期望EditorBrowsableState.Never

来自MSDN论坛的一些信息概述了这种情况的原因:

从工具UI Spy中,我们可以看到PropertyGrid只是一个面板,它由三个Windows控件组成。我们的KeyDown事件应该由子控件表格处理。 结构如下:

-"pane" "PropertyGrid"
  --"pane" "Description Pane"
  --"table" "Properties Window"
  --"tool bar" "ToolBar"

建议的解决方案(也在 MSDN 链接中提供)是使用本地系统调用来检索窗口/控件信息,子类化 NativeWindow 并重写 WndProc 方法以处理您喜欢的事件,在这种情况下是 KeyDown

1
嗯...那真是太奇怪和令人沮丧了。我的意思是,我们已经到了2010年,这看起来像是旧的COM遗留问题 :-( - Mehdi LAMRANI
这并不是“非常奇怪”,也与COM无关,这只是Windows输入的工作方式!输入始终进入具有焦点的控件。就是这样。由于PropertyGrid是一个复合控件,并且具有所有这些用于编辑值的TextBoxes和Comboboxes,您想要接收什么类型的KeyDown事件?全部吗?在这种情况下,重写PropertyGrid的ProcessKeyPreview并执行您的逻辑。 - liggett78
我想举个例子,比如说我想改变默认的“Enter”键行为来退出PBox(还有其他)。好的,我明白:在可能被PGrid控件访问之前,文本框和控件会捕获KeyEvents。但是,这仍然非常不方便,解决方法很繁琐(在我看来)。 - Mehdi LAMRANI

-1
您可以从PropertyGrid的子类中覆盖此方法,以获取一些来自Windows消息的关键信息。
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)

-2

CSharp PropertyGrid 事件

// Property grid events can’t be easily subscribed to however there is way to get at the KeyUp event without impacting operation. 
// Note: The KeyDown event can be subscribed to in the same manner but the propertygrid is NOT updated with the key presses. 
// This code is added in hope it may help someone else solve the problem. It is not offered as a total solution.

// First define a class variable to indicate that events have been added.
private bool m_bPropertyGridEventsAdded = false;

public GlassInfoEntryPage(ViewBase view)
        : base(view)
    {
        InitializeComponent();

        // Subscribe to SelectedGridItemChanged
        m_PropertyGrid.SelectedGridItemChanged += M_PropertyGrid_SelectedGridItemChanged;
    }

// Now define a SelectedGridItemChanged Event Handler
private void M_PropertyGrid_SelectedGridItemChanged(object sender, SelectedGridItemChangedEventArgs e)
{
        int nXlocation;
        int nYlocation;

        PropertyGrid oPropertyGrid;
        Control oControl;

        if (m_bPropertyGridEventsAdded == false)
        {
            oPropertyGrid = (PropertyGrid)sender;

            // Search the Property Grid for a PropertyGridView Control so events can be added to it
            for (nXlocation = 0; nXlocation < oPropertyGrid.Width; nXlocation += 10)
            {
                for (nYlocation = 0; nYlocation < oPropertyGrid.Height; nYlocation += 10)
                {
                    oControl = m_glassInfoPropertyGrid.GetChildAtPoint(new Point(nXlocation, nYlocation));

                    if (oControl != null)
                    {
                        if (oControl.GetType().ToString() == "System.Windows.Forms.PropertyGridInternal.PropertyGridView")
                        {
                            // Add Events here
                            oControl.Controls[1].KeyUp += MyCode_KeyUp;
                            m_bPropertyGridEventsAdded = true;
                            break;
                        }
                    }
                }

                if (m_bPropertyGridEventsAdded == true)
                {
                    break;
                }
            }
        }
    }        

// Handle the events
private void MyCode_KeyUp(object sender, KeyEventArgs e)
{
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接