Reputation: 4777
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.
Upvotes: 1
Views: 3223
Reputation: 695
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;
}
}
}
Upvotes: 5
Reputation: 695
It requires a little trickery, but this should do it:
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");
}
}
}
Upvotes: 1