Winforms 如何在windows窗体PropertyGrid中捕获滚动事件

Winforms 如何在windows窗体PropertyGrid中捕获滚动事件,winforms,propertygrid,Winforms,Propertygrid,我正在尝试同步两个属性网格的垂直滚动条。其思想是当用户滚动一个属性网格时,另一个属性网格的滚动量相同 我的第一种方法是处理scroll事件,但PropertyGrid似乎不会生成此类事件。我查看了PropertyGrid中包含的控件,其中有一个PropertyGridView,我打赌是带有滚动条的控件 有人知道实现我想要的目标的方法吗 谢谢。这需要一些技巧,但这应该可以做到: using System; using System.Windows.Forms; using System.Refle

我正在尝试同步两个属性网格的垂直滚动条。其思想是当用户滚动一个属性网格时,另一个属性网格的滚动量相同

我的第一种方法是处理scroll事件,但PropertyGrid似乎不会生成此类事件。我查看了PropertyGrid中包含的控件,其中有一个PropertyGridView,我打赌是带有滚动条的控件

有人知道实现我想要的目标的方法吗


谢谢。

这需要一些技巧,但这应该可以做到:

using System;
using System.Windows.Forms;
using System.Reflection;

namespace WindowsApplication1 {
    public partial class Form1 : Form {
        Control m_pgv = null;

        public Form1 () {
            InitializeComponent ();

            // Set the Property Grid Object to something
            propertyGrid1.SelectedObject = dataGridView1;

            // Loop through sub-controls and find PropertyGridView
            foreach (Control c in propertyGrid1.Controls) {
                if (c.Text == "PropertyGridView")
                {
                    m_pgv = (Control)c;
                    break;
                }
            }

            // Reflection trickery to get a private field,
            // scrollBar in this case
            Type t = m_pgv.GetType ();
            FieldInfo f = t.GetField("scrollBar", 
                BindingFlags.Instance | BindingFlags.NonPublic);

            // Get the scrollBar for our PropertyGrid and add the event handler
            ScrollBar sb = (ScrollBar) f.GetValue(m_pgv);
            sb.Scroll +=  new ScrollEventHandler(propertyGrid1_Scroll);
        }

        private void propertyGrid1_Scroll (object sender, ScrollEventArgs e) {
            System.Console.WriteLine ("Scroll");
        }
    }
}

这需要一些技巧,但这应该可以做到:

using System;
using System.Windows.Forms;
using System.Reflection;

namespace WindowsApplication1 {
    public partial class Form1 : Form {
        Control m_pgv = null;

        public Form1 () {
            InitializeComponent ();

            // Set the Property Grid Object to something
            propertyGrid1.SelectedObject = dataGridView1;

            // Loop through sub-controls and find PropertyGridView
            foreach (Control c in propertyGrid1.Controls) {
                if (c.Text == "PropertyGridView")
                {
                    m_pgv = (Control)c;
                    break;
                }
            }

            // Reflection trickery to get a private field,
            // scrollBar in this case
            Type t = m_pgv.GetType ();
            FieldInfo f = t.GetField("scrollBar", 
                BindingFlags.Instance | BindingFlags.NonPublic);

            // Get the scrollBar for our PropertyGrid and add the event handler
            ScrollBar sb = (ScrollBar) f.GetValue(m_pgv);
            sb.Scroll +=  new ScrollEventHandler(propertyGrid1_Scroll);
        }

        private void propertyGrid1_Scroll (object sender, ScrollEventArgs e) {
            System.Console.WriteLine ("Scroll");
        }
    }
}

这一个显示了与相邻PropertyGridView的同步。注意,您必须扩展它以处理用户单击任一控件的情况。此版本更新propertyGrid2以匹配propertyGrid1,但反之亦然

using System;
using System.Windows.Forms;
using System.Reflection;

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        Control m_pgv_1 = null;
        Control m_pgv_2 = null;
        MethodInfo m_method_info;

        public Form1 ()
        {
            InitializeComponent ();

            // Set the Property Grid Object to something
            propertyGrid1.SelectedObject = dataGridView1;
            propertyGrid2.SelectedObject = dataGridView1;

            // Loop through sub-controlls and find PropertyGridView
            m_pgv_1 = FindControl (propertyGrid1.Controls, "PropertyGridView");
            m_pgv_2 = FindControl (propertyGrid2.Controls, "PropertyGridView");

            // Reflection trickery to get a private/internal field
            // and method, scrollBar and SetScrollOffset in this case
            Type type = m_pgv_1.GetType ();
            FieldInfo f = FindField (type, "scrollBar");
            m_method_info = FindMethod (type, "SetScrollOffset");

            // Get the scrollBar for our PropertyGrid and add the event handler
            ((ScrollBar)f.GetValue (m_pgv_1)).Scroll +=
                new ScrollEventHandler (propertyGrid1_Scroll);
        }

        private void propertyGrid1_Scroll (object sender, ScrollEventArgs e)
        {
            System.Console.WriteLine ("Scroll");

            // Set the new scroll position on the neighboring
            // PropertyGridView
            object [] parameters = { e.NewValue };
            m_method_info.Invoke (m_pgv_2, parameters);
        }

        private static Control FindControl (
            Control.ControlCollection controls, string name)
        {
            foreach (Control c in controls)
            {
                if (c.Text == name)
                    return c;
            }

            return null;
        }

        private static MethodInfo FindMethod (Type type, string method)
        {
            foreach (MethodInfo mi in type.GetMethods ())
            {
                if (method == mi.Name)
                    return mi;
            }

            return null;
        }

        private static FieldInfo FindField (Type type, string field)
        {
            FieldInfo f = type.GetField (field,
               BindingFlags.Instance | BindingFlags.NonPublic);

            return f;
        }
    }
}

这一个显示了与相邻PropertyGridView的同步。注意,您必须扩展它以处理用户单击任一控件的情况。此版本更新propertyGrid2以匹配propertyGrid1,但反之亦然

using System;
using System.Windows.Forms;
using System.Reflection;

namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        Control m_pgv_1 = null;
        Control m_pgv_2 = null;
        MethodInfo m_method_info;

        public Form1 ()
        {
            InitializeComponent ();

            // Set the Property Grid Object to something
            propertyGrid1.SelectedObject = dataGridView1;
            propertyGrid2.SelectedObject = dataGridView1;

            // Loop through sub-controlls and find PropertyGridView
            m_pgv_1 = FindControl (propertyGrid1.Controls, "PropertyGridView");
            m_pgv_2 = FindControl (propertyGrid2.Controls, "PropertyGridView");

            // Reflection trickery to get a private/internal field
            // and method, scrollBar and SetScrollOffset in this case
            Type type = m_pgv_1.GetType ();
            FieldInfo f = FindField (type, "scrollBar");
            m_method_info = FindMethod (type, "SetScrollOffset");

            // Get the scrollBar for our PropertyGrid and add the event handler
            ((ScrollBar)f.GetValue (m_pgv_1)).Scroll +=
                new ScrollEventHandler (propertyGrid1_Scroll);
        }

        private void propertyGrid1_Scroll (object sender, ScrollEventArgs e)
        {
            System.Console.WriteLine ("Scroll");

            // Set the new scroll position on the neighboring
            // PropertyGridView
            object [] parameters = { e.NewValue };
            m_method_info.Invoke (m_pgv_2, parameters);
        }

        private static Control FindControl (
            Control.ControlCollection controls, string name)
        {
            foreach (Control c in controls)
            {
                if (c.Text == name)
                    return c;
            }

            return null;
        }

        private static MethodInfo FindMethod (Type type, string method)
        {
            foreach (MethodInfo mi in type.GetMethods ())
            {
                if (method == mi.Name)
                    return mi;
            }

            return null;
        }

        private static FieldInfo FindField (Type type, string field)
        {
            FieldInfo f = type.GetField (field,
               BindingFlags.Instance | BindingFlags.NonPublic);

            return f;
        }
    }
}

然后,如何让另一个控件滚动以匹配第一个控件?使用此代码,我能够同步两个滚动条。当我移动一个时,另一个也相应地移动。问题是内容不能随滚动条滚动。我想最好还是放弃我原来的想法。你必须在相邻的PropertyGridView上调用SetScrollPosition()。请参阅我的第二个答案。然后如何让另一个控件滚动以匹配第一个?使用此代码,我能够同步两个滚动条。当我移动一个时,另一个也相应地移动。问题是内容不能随滚动条滚动。我想最好还是放弃我原来的想法。你必须在相邻的PropertyGridView上调用SetScrollPosition()。见我的第二个答案。