Click here to Skip to main content
Click here to Skip to main content

PropertyGrid and Drop Down properties

By , 7 Feb 2005
 

Sample Image - DropDownProperties.jpg

Introduction

This article discusses three types of drop down properties:

  1. Dynamic Enumeration - View a drop down combo box with dynamic values.
  2. Images & Text - Show different bitmaps based on the value in the drop down list.
  3. Drop Down Editor - Show a custom UI type editor as a drop down form.

Dynamic Enumeration

Often, we would like to show dynamic values in a combo box, avoiding hard coded values. Instead, we may load them from a database or text files to support globalization and more. In this case, the property is called Rule, and rules are loaded from the RichTextBox. First, we define an internal class, having a string array containing the list of values.

internal class HE_GlobalVars
{
    internal static string[] _ListofRules;
}

We also define a type converter as follows:

public class RuleConverter : StringConverter
{
    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
        //true means show a combobox
        return true;
    }

    public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
    {
        //true will limit to list. false will show the list, 
        //but allow free-form entry
        return true;
    }

    public override System.ComponentModel.TypeConverter.StandardValuesCollection 
           GetStandardValues(ITypeDescriptorContext context)
    {
        return new StandardValuesCollection(HE_GlobalVars._ListofRules);
    }
}

The Rule property is defined as follows:

<Browsable(true)>
[TypeConverter(typeof(RuleConverter))]
public string Rule
{

    //When first loaded set property with the first item in the rule list.
    get {
        string S = "";
        if (_Rule != null)
        {
            S = _Rule;
        }
        else
        {
            if (HE_GlobalVars._ListofRules.Length > 0)
            {
                //Sort the list before displaying it
                Array.Sort(HE_GlobalVars._ListofRules);
                S = HE_GlobalVars._ListofRules[0];
            }
        }
        return S;
    }
    set{ _Rule = value; }
}

Then, from the application itself, we fill the list of rules:

private void UpdateListofRules()
{
    int _NumofRules = richTextBox1.Lines.Length;
    HE_GlobalVars._ListofRules = new string[_NumofRules];
    for(int i = 0; i <= _NumofRules - 1; i++)
    {
        HE_GlobalVars._ListofRules[i] = richTextBox1.Lines[i];
    }
}

Images & Text

Some property types such as Image, Color, or Font.Name paint a small representation of the value just to the left of the space where the value is shown. This is accomplished by implementing the UITypeEditor PaintValue method. When the property browser renders a property value for a property that defines an editor, it presents the editor with a rectangle and a Graphics object with which to paint.

Here the property named SourceType is shown as a drop down list where each value has its own image located next to it. Images are loaded from a resource file.

public enum HE_SourceType {LAN, WebPage, FTP, eMail, OCR}

public class SourceTypePropertyGridEditor : UITypeEditor
{
    public override bool GetPaintValueSupported(ITypeDescriptorContext context)
    {
        //Set to true to implement the PaintValue method
        return true;
    }

    public override void PaintValue(PaintValueEventArgs e)
    {
        //Load SampleResources file
        string m = this.GetType().Module.Name;
        m = m.Substring(0, m.Length - 4);
        ResourceManager resourceManager =
            new ResourceManager (m + ".ResourceStrings.SampleResources", 
            Assembly.GetExecutingAssembly());
        int i = (int)e.Value;
        string _SourceName = "";
        switch(i)
        {
            case ((int)HE_SourceType.LAN): _SourceName = "LANTask"; break;
            case ((int)HE_SourceType.WebPage): _SourceName = "WebTask"; break;
            case ((int)HE_SourceType.FTP): _SourceName = "FTPTask"; break;
            case ((int)HE_SourceType.eMail): _SourceName = "eMailTask"; break;
            case ((int)HE_SourceType.OCR): _SourceName = "OCRTask"; break;
        }

        //Draw the corresponding image
        Bitmap newImage = (Bitmap)resourceManager.GetObject(_SourceName);
        Rectangle destRect = e.Bounds;
        newImage.MakeTransparent();
        e.Graphics.DrawImage(newImage, destRect);
    }
}

[Editor(typeof(SourceTypePropertyGridEditor), 
        typeof(System.Drawing.Design.UITypeEditor))]
public HE_SourceType SourceType
{
    get{return _SourceType;}
    set{_SourceType = value;}
}

Drop Down Editor

Visual Studio .NET uses type converters for text-based property editing and code serialization. Some built-in types, such as Color or DockStyle, get a specialized user interface in the property grid as well as text support. If you would like to supply a graphical editing interface for your own property types, you can do so by supplying a UI type editor as a drop-down editor user interface.

First, we create a form to be used as an editor. When initializing the form, we must set its TopLevel property to false. To make it caption-less, we have to set the following properties:

this.MaximizeBox = false;
this.MinimizeBox = false;
this.ControlBox = false;
this.ShowInTaskbar = false;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;

The Contrast property is used in this case.

The following code uses the IServiceProvider passed to EditValue. It asks it for the IWindowsFormsEditorService interface (which is defined in the System.Windows.Forms.Design namespace). This service provides the facility for opening a drop-down editor, we simply call the DropDownControl method on it, and it will open whichever control we pass. It sets the size and location of the control so that it appears directly below the property when the drop-down arrow is clicked.

When we write the UI editor class itself, we have a choice as to the kind of user interface we can supply. We can either open a modal dialog or supply a pop-up user interface that will appear in the property grid itself. We indicate this by overriding the GetEditStyle method. This method returns a value from the UITypeEditorEditStyle enumeration, either Modal or DropDown. For either type of user interface, we must also override the EditValue method, which will be called when the user tries to edit the value. The value returned from EditValue will be written back to the property. It will call EditValue when the arrow button is clicked.

public class ContrastEditor : UITypeEditor
{
    public override UITypeEditorEditStyle 
           GetEditStyle(ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.DropDown;
    }

    public override object EditValue(ITypeDescriptorContext context, 
                            IServiceProvider provider, object value)
    {
        IWindowsFormsEditorService wfes = 
           provider.GetService(typeof(IWindowsFormsEditorService)) as
           IWindowsFormsEditorService;

        if (wfes != null)
        {
            frmContrast _frmContrast = new frmContrast();
            _frmContrast.trackBar1.Value = (int) value;
            _frmContrast.BarValue = _frmContrast.trackBar1.Value;
            _frmContrast._wfes = wfes;

            wfes.DropDownControl(_frmContrast);
            value = _frmContrast.BarValue;
        }
        return value;
    }
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Ronit H
Israel Israel
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionThank you every much.memberyuancx_zjgsu3 Jul '12 - 12:59 
It is the code I need most. Thank you.
GeneralMy vote of 5memberCarl.Hinkle22 Feb '12 - 11:10 
This solved the problem I've been wrestling with all afternoon Smile | :) Thanks!
QuestionAnd how can I make the Contrast value update during sliding?memberXtraMarc27 Mar '09 - 13:01 
Hi,
 
thanks for the tutorial, it was very helpful to me. I just have the problem, that I'd like to make the int value of Contrast n the Grid Update WHILE I drag the slider. How does that work. The slider doesn't know any more which value he is to update. Could you give me an example?
 
Cheers
 
Marc
GeneralJust some other stuffmemberHuanacaraz7 Apr '08 - 23:26 
First thanx for this article, it helps me much.
Second - to provide custom UI editor thers no need to design its as Form, but better to use CustomControl, or even any class derived from Control.
(I used ListBox to simulate inline dropdown control to show font list:
 
variables:
static MyObject[] globalarray;
ListBox Box1;
IWindowsFormsEditorService wfes;

 
in constructor:
Box1 = new ListBox();
Box1.BorderStyle = BorderStyle.None;
Box1.DrawMode = DrawMode.OwnerDrawFixed;
Box1.Click += new EventHandler(Box1_Click);
Box1.DrawItem += new DrawItemEventHandler(Box1_DrawItem);

 
in EditValue(..)
...
wfes = (IWindowsFormsEditorService)...;
Box1.Items.Clear();
Box1.Items.AddRange(globalarray);
Box1.SelectedItem = value;
Box1.Height = 150;
wfes.DropDownControl(Box1);
wfes = null;
if (Box1.SelectedItem != null) return Box1.SelectedItem;
...

 
in Box1_Click:
wfes.CloseDropDown();
 
in Box1_DrawItem: (showing font written by self Smile | :)
e.DrawBackground();
MyObject item = (MyObject)Box1.Items[e.Index];
//provide self font, but take size and format from original...
using (Font f = item.GetFont(e.Font))
{
using (Brush b = new SolidBrush(e.ForeColor))
{
e.Graphics.DrawString(item.ToString(), f, b, e.Bounds, StringFormat.GenericDefault);
}
}
e.DrawFocusRectangle();

GeneralWowmemberjigs_19711 Apr '08 - 3:45 
What a big help, Many thanks.
GeneralCould Be Simplermembersabrown10024 Oct '07 - 8:38 
It is much easier to perform Dynamic Enumeration than in your sample. Just use an enum as your property type.
GeneralThanks, just saved me hours of work!memberChris Byrne10 Oct '07 - 2:22 
Thanks, just saved me hours of work!Smile | :)
GeneralVB.Net example of dynamic dropdown propertiesmemberTyler W. Cox20 Jul '07 - 5:35 
Ronit H was an excellent source for figuring out how to get the property grid to work. If anyone needs a VB.Net example of how to implement dynamic properties I have posted one here:
http://www.codeproject.com/vb/net/DynamicDropDownProperties.asp
GeneralNice jobmemberMember #198316831 Jan '07 - 2:28 
it is so clear to explain and so goog to be used.
 
sqjt
GeneralAvoiding global in dynamic listmembercshung17 Jan '07 - 8:20 
It is well known that using global is no good, a singleton doesn't make that smell better.
Are there way not to pass the array through global variables.
 
I attempted, but unfortunately that isn't easy. First, you cannot have non-default constructor for the TypeConverter.
Second, the ITypeDescriptorContext is always null, make it unable to query the Property that it is converting for.
 
Anyone out there has a good solution for that?

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 7 Feb 2005
Article Copyright 2005 by Ronit H
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid