Click here to Skip to main content
15,885,189 members
Articles / Programming Languages / C#

Enabling/disabling properties at runtime in the PropertyGrid

Rate me:
Please Sign up or sign in to vote.
4.96/5 (19 votes)
3 Feb 2011CPOL2 min read 67.9K   12   10
How to enable/disable properties at runtime in the PropertyGrid.

Introduction

Many people know about the benefits of using PropertyGrids in user interfaces.

You probably know about the System.ComponentModel namespace, and how it can help you in customizing the behavior of classes and their properties when edited through controls like the PropertyGrid. One of the attributes you can find in that namespace is ReadOnly, which will make a property to be read only and appear in gray (even if it has the Set accessor).

The problem with this attribute is that it must be defined at build-time. Sometimes, it is very useful (and improves the user experience quite a bit), to enable or disable properties at runtime.

Imagine the following example, where we have a “UserData” class:

C#
public class UserData
{
    ...

    public string Country
    {
        get { return mCountry; }
        set { mCountry = value; }
    }
    public string State
    {
        get { return mState; }
        set { mState = value; }
    }
}

Now, imagine you want the user to fill the State field only in the case he selects US as his Country. In such a case, you need to make this change at Runtime.

There are several solutions for this, but I find the following one to be the most elegant, as it's coded in the UserData class itself. The final code looks like:

C#
[RefreshProperties(System.ComponentModel.RefreshProperties.All)]
[ReadOnly(false)]
public string Country
{
  get { return mCountry; }
  set
      {
      mCountry = value;
      PropertyDescriptor descriptor = TypeDescriptor.GetProperties(this.GetType())["State"];
      ReadOnlyAttribute attribute = (ReadOnlyAttribute)
                                    descriptor.Attributes[typeof(ReadOnlyAttribute)];
      FieldInfo fieldToChange = attribute.GetType().GetField("isReadOnly", 
                                       System.Reflection.BindingFlags.NonPublic | 
                                       System.Reflection.BindingFlags.Instance);
      fieldToChange.SetValue(attribute, mCountry != "U.S.");
      }
}

[ReadOnly(true)]
public string State
{
   get { return mState; }
   set { mState = value; }
}

Some Tips

  1. We obviously change the ReadOnly attribute of the State property in the setter accessor of the property Country. That's the exact point where we know if State should be enabled or disabled.
  2. It is important to add the RefreshProperties attribute to the Country property. That will force the PropertyGrid control to refresh all its properties every time the value of Country changes, reflecting the changes we made to the attributes of State.
  3. In order for all this to work properly, it is important to statically define the ReadOnly attribute of every property of the class to whatever value you want. If not, changing the attribute at runtime that way will wrongly modify the attributes of every property of the class.

Hope it helps!

More Info

Cheers!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Spain Spain
Inaki Ayucar is a Microsoft MVP in DirectX/XNA, and a software engineer involved in development since his first Spectrum 48k, in the year 1987. He is the founder and chief developer of The Simax Project (www.simaxvirt.com) and is very interested in DirectX/XNA, physics, game development, simulation, C++ and C#.

His blog is: http://graphicdna.blogspot.com

To contact Inaki: iayucar@simax.es

Comments and Discussions

 
QuestionGood article but pay attention to tip nr.3 Pin
Member 118185804-Sep-17 1:05
Member 118185804-Sep-17 1:05 
QuestionHow to make it work with Xceed WPF Toolkit Pin
Jiří Skála4-Aug-15 23:07
Jiří Skála4-Aug-15 23:07 
QuestionSimple, Elegant and to the Point Pin
StevehNpe7-Nov-14 17:30
StevehNpe7-Nov-14 17:30 
GeneralVote of 5 Pin
Lee Zhe Heng28-Nov-13 19:18
professionalLee Zhe Heng28-Nov-13 19:18 
GeneralMy vote of 5 Pin
Stefano Manni10-Oct-12 21:24
Stefano Manni10-Oct-12 21:24 
GeneralMy vote of 5 Pin
Member 41913665-Jun-12 20:03
Member 41913665-Jun-12 20:03 
QuestionIn case of a collection of UserData objects. Pin
Swiebertje26-May-11 5:53
Swiebertje26-May-11 5:53 
QuestionAsk question for enable/disable article [modified] Pin
Sports Kuo23-Feb-11 0:34
Sports Kuo23-Feb-11 0:34 
AnswerRe: Ask question for enable/disable article [modified] Pin
Member 1070314726-Jun-14 2:56
Member 1070314726-Jun-14 2:56 
GeneralMy vote of 5 Pin
MrRexx22-Feb-11 21:28
MrRexx22-Feb-11 21:28 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.