Blogs

Paul Kimmel's Blog

Imagineering with the PropertyGridControl

     

The PropertyGridControl is an implementation of the XtraVerticalGrid. At its core is roughly a grid with row headers instead of column headers, property names, and property values. Associate an object with a grid and use reflection to read all of the property names and values into a collection and bind to the grid. If one were to oversimplify what the property grid control is then that about captures it. Of course, if you want robust functionality then there is the difficulty of nested row headers instead of column headers, properties, property editors, updating bound objects and dozens of details that go into it. (El Diablo is always in the details.)

Since DXperience from DevExpress already provides us with a PropertyGridControl derived from the XtraVerticalGrid our less challenging difficulty is what do we do with it. Well, Visual Studio uses the a Properties window to display properties of all kinds and let’s developers manipulate these properties without writing code. Clearly, if you are writing some kind of editor then you might want a property grid. That is an obvious hindsight. Here are a couple of ideas for other uses for the PropertyGridControl. Suppose you wanted to write a user customizable application.The PropertyGridControl binds to objects and provides a UI for changing an object’s state. Let the user change state at runtime and you have some user configurability. A second use might be to create a demo or training application. Such an application would let a user point at a component or control and tweak the properties to experience the results. That’s the demo I created for this blog.

Here is a scenario I used to encounter all of the time: an objective was to provide an experiential environment where trainees or potential customers were interested in learning about a product or technology. The difficulty is some invitees weren’t tech-savvy and many times the computers didn’t have the right tools or versions of those tools, like Visual Studio. Dragging pre-configured PCs around or installing Visual Studio for a couple of days training was a huge expense. A possible solution—which could easily apply to demoing our controls and components as demoing your custom applications would be to add a demo mode that shows a PropertyGridControl and let’s a non-technical user experience customizations. All that would be needed is the .NET Framework and a brief install for the demo application.

The sample in this section uses a modeless window (WinForm) with a PropertyGridControl on it. The other form has some DevExpress controls on it, including a RichEditControl, an XtraGrid (GridControl), and two basic buttons. The code let’s you hover the mouse cursor over any of the controls and the PropertyGridControl is bound to that control. Change a setting in the PropertyGridControl and you automatically see the change reflected in the running control. For my purposes this might make moderately useful demo to let people see what our LookAndFeel technology—which supports skinning—looks like in action without compiling, debugging, and restarting over and over. (I think in the context of a conference or technology fair this may be a snappier use of available time.) This particular demo—Listings 1 and 2—also binds all of the controls on the demo Form to a ComboBoxEdit control on the property browser form letting the user pick a control from the combo as well as hover.

Listing 1 just has a RichEditControl, two WinForms buttons, and an XtraGrid (GridControl) bound to the Northwind database’s Orders table. The only real code is the Form_Load event that loads the XtraGrid’s data and calls an Update method on Form1—more on this later—and a MouseHover event bound to every control’s MouseHover event. MouseHover calls an overloaded instance of Form1.Update. Here is Listing 1. Listing 2 does all of the real work.

Listing 1: richEditControl1_MouseHover is reused for the two buttons, the Form, the XtraGrid, and the RichEditControl’s MouseHover event.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace PropertyGridDemo
{
  public partial class Form2 : Form
  {
    public Form2()
    {
      InitializeComponent();
    }

    private void Form2_Load(object sender, EventArgs e)
    {
      // TODO: This line of code loads data into the 'northwindDataSet.Orders' table. You can move, or remove it, as needed.
      this.ordersTableAdapter.Fill(this.northwindDataSet.Orders);
      Form1.Update(this);
    }

    private void richEditControl1_MouseHover(object sender, EventArgs e)
    {
      Form1.Update(sender);
    }
  }
}

in Form2_Load.Update the form instance is sent and this is used to fill Form1’s ComboBoxEdit control with controls on Form2. In MouseHover sender is the control being hovered over and this version of Update updates the PropertyGridControl. Listing 2 contains the code for the form containing the PropertyGridControl.

Listing 2: This form contains a ComboBoxEdit control and PropertyGridControl.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraVerticalGrid.Rows;
using DevExpress.Utils.Win;
using DevExpress.Utils;
using System.Reflection;
using DevExpress.XtraEditors;

namespace PropertyGridDemo
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }

    private static Form1 form = null;
    public static void Update(object selected)
    {
      CreateForm();
      if (selected == null) return;
      form.propertyGridControl1.SelectedObject = selected;
      form.Text = selected.GetType().Name;
    }

    private static void CreateForm()
    {
      if (form == null)
      {
        form = new Form1();
        form.TopMost = true;
        form.StartPosition = FormStartPosition.CenterScreen;
      }

      form.Show();
    }

    public static void Update(Form referenceForm)
    {
      CreateForm();
      if (referenceForm == null) return;

      form.comboBoxEdit1.Properties.Items.Add(referenceForm);
      AddChildren(referenceForm);
    }

    private static void AddChildren(Control control)
    {
      foreach (Control child in control.Controls)
      {
        form.comboBoxEdit1.Properties.Items.Add(child);
        if (child.HasChildren)
          AddChildren(child);
      }

    }

    public static void CloseUp()
    {
      if (form != null)
      {
        form.Close();
        form.Dispose();
        form = null;
      }
    }

    private void Form1_FormClosed(object sender, FormClosedEventArgs e)
    {
      form = null;
    }

    private void comboBoxEdit1_SelectedValueChanged(object sender, EventArgs e)
    {
      propertyGridControl1.SelectedObject =
        (sender as ComboBoxEdit).SelectedItem;
    }

  }
}

Listing 2 uses a static helper method technique that I employ to treat a dialog much the same way MessageBox.ShowMessageDialog works. Update(object selected) creates the static Form field and binds the object parameter to the propertyGridControls1.SelectedObject property. That’s at the heart of what it takes to populate the PropertyGridControl—set SelectedObject. The Form’s Text property is set to the object parameters type name. CreateForm creates an instance of the containing Form class and shows it as a modeless dialog. The second version of Update accepts a form object and recursively adds child controls to the ComboBoxEdit control. CloseUp cleans up the static form field. Finally, the ComboBoxEdit.SelectedValueChanged event updates the PropertyGridControl.SelectedObject right from the ComboBoxEdit.SelectedItem property. Since the DevExpress ComboBoxEdit control can hold objects you can store references to controls right in the ComboBoxEdit control. Figures 3 and 4 show the reference form and the form containing the PropertyGridControl, respectively.

image
Figure 1: A reference form—which intentionally plain—so when properties are changed the changes are noticeable.

image
Figure 2: The form containing the PropertyGridControl; change a property and see the change reflected on the reference form (Figure 1).

In this demo if I wanted to demo the LookAndFeel property for the RichEditControl I could select the RichEditControl from the ComboBoxEdit control, expand LookAndFeel, change the SkinName to Lilian, and UseDefaultLookAndFeel to False (see Figures 3 and 4).

image
Figure 3: Note the subtle change to the RichEditControl caused by the runtime property settings changes (see Figure 4).

image 
Figure 4: A runtime demo tool  that shows changes without change, compile, and debug steps.

A similar approach could be used to demo almost any applications customization settings. Just brain storming here, but something like this might work for non-technical sales  people, to speed up demos in general, or for a training environment. For hardcore developers a better use for a property grid might be for a custom designer (or development environment) or for instrumentation of an application.

Published Mar 23 2010, 07:55 PM by Paul Kimmel (DevExpress)
Bookmark and Share

Comments

 

Sigurd Decroos said:

I'm using the propertygrid in my SQL Parser. A form on which my users can enter a SQL statement and the result is shown in a grid, pivot or chart. Clicking the result grid, pivot or chart, changes the propertygrid. The user can change what he/she wants and later the changes can be stored with the grid, pivot or chart. A combobox with the columns/fields makes everything even more customizable.

Thank you for this component, it made my SQL Parser so much more powerfull!

March 23, 2010 6:02 PM
 

Paul Kimmel (DevExpress) said:

Sigurd:

Good to hear. There are only a very few of us and many of you. I am always curious to hear about the ingenious ways that customers use DevExpress tools. I have seen several neat, professional solutions but probably a very small percentage of them.

March 23, 2010 7:07 PM
 

James Foye said:

I used this in a program a couple of years ago. I started out using the Windows property control, and that was ugly. I switched to using the Devex control and was very happy with it.

March 24, 2010 5:57 PM
More from DevExpress
Live Chat
Have a pre-sales question?
Need assistance with your evaluation?
We are here to help.
Chat is one of the many ways you can contact members of the DevExpress Team. We are available Monday-Friday between 8:30am and 5:00pm Pacific Time.
If you need additional product information, require pre-sales assistance, or want help with your order, write to us at info@devexpress.com or call us at
+1 (818) 844-3383.