R – How to catch scroll events in windows forms PropertyGrid

propertygridwinforms

I'm trying to synchronize the vertical scrollbars of two property grids. The idea is when a user scrolls one property grid the other property grid scrolls by the same amount.

My first approach was to handle the scroll event but it seems PropertyGrid doesn't generate this kind of event. I looked into the controls contained inside the PropertyGrid and there is a PropertyGridView, that I bet is the control with the scrollbar.

Does anybody know a workaround to achieve what I want?

Thank you.

Best Answer

This one shows the synchronization with the neighboring PropertyGridView. Note you will have to extend it to handle the user clicking on either control. This version updates propertyGrid2 to match propertyGrid1, but not vice versa.

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