Click here to Skip to main content
15,886,026 members
Articles / Programming Languages / C#
Article

The PropertyGrid: Overriding Class Attributes

Rate me:
Please Sign up or sign in to vote.
4.81/5 (14 votes)
17 Jan 2008CPOL4 min read 68.2K   1.5K   61   4
Dynamically control any attribute, including DefaultValues, Categories, Descriptions, DisplayNames, ReadOnly attributes, Property sort order and more.
Screenshot - ScreenShot_DynDemo.gif

Introduction

The DynamicPropWrapper class wraps an existing class and filters the property information that the .NET PropertyGrid displays. The purpose for this is mainly to control the ReadOnly and DefaultValues for each property dynamically in the code. Other features include dynamic modification of the Categories, Descriptions, DisplayNames, Property sorting order and more.

  • Two methods for handling default values
  • Wraps an existing class, making it a drop-in solution
  • Overrides attributes with one line of code
  • Preserves all existing attribute information that may already be defined in your class
  • Add/override any attribute desired

Using the Code

To use the DynamicPropWrapper class, do the following:

C#
// This is the class object whose properties you want
// to see in the PropertyGrid.

mTestObject = new DemoClass1;

// The DynamicPropWrapper is the Main class used
// to filter property information from the class above.

mDynPropWrapper = new DynamicPropWrapper(mTestObject);

// The PropertyGrid.SelectedObject gets set to the
// DynamicPropWrapper.DynamicDescriptor property. This
// allows the DynamicPropWrapper class to describe the
// type information for mTestObject.

propertyGrid1.SelectedObject = mDynPropWrapper.DynamicDescriptor;

Overriding Attributes

Overriding a property attribute can be done with one line of code:

C#
// Overriding/Adding a DefaultValue

mDynPropWrapper["MyPropertyName"].Overrides.Replace_
        (new DefaultValueAttribute("New Default Value"));

// Overriding/Adding a ReadOnly

mDynPropWrapper["MyPropertyName"].Overrides.Replace_
                (new ReadOnlyAttribute(true));

The DefaultValue

First, note the following: PRB: XML Serialization: System.Xml.XmlSerializer Does Not Serialize Default Values. Microsoft recognized this as a problem in .NET 1.1 and claimed it would be resolved in its next framework release. Apparently it never got done. The result is that any class property whose value matches the default value will not be serialized by the XmlSerializer. This was no doubt done intentionally in an effort to reduce the size of the final output stream, but it also means that the class object it was serialized with is required to re-construct the data.

Using the DynamicPropWrapper class, you can omit DefaultValueAttributes from your classes and control the default value in two ways:

  1. By overriding the default values for each property - see the example above
  2. By using a global DefaultValueObject for all property default values - see the example below
C#
// This is the class object whose properties you want
// to see in the PropertyGrid.

mTestObject = new DemoClass1;

// This is the class that represents the default values
// for mTestObject.

mTestObject_Defaults = new DemoClass1();

// The DynamicPropWrapper is the Main class used
// to filter property information from the class above.

mDynPropWrapper = new DynamicPropWrapper(mTestObject);

// Assign a global DefaultValueObject.

mDynPropWrapper.OverrideProps.DefaultValueObject = mTestObject_Defaults;

// The PropertyGrid.SelectedObject gets set to the
// DynamicPropWrapper.DynamicDescriptor property. This
// allows the DynamicPropWrapper class to describe the
// type information for mTestObject.

propertyGrid1.SelectedObject = mDynPropWrapper.DynamicDescriptor;

You can now use mTestObject_Defaults to manage the default values for mTestObject. The DynamicPropWrapper class will first look for a global DefaultValueObject. If one is not found, it looks in the attributes collection for a DefaultValueAttribute. If a DefaultValue override has been set, it will use this. If there is no DefaultValueObject and no DefaultValue override, it will use the "hard-coded" DefaultValueAttribute in the class (if one exists).

Property Sorting

Properties can be ordered in two ways:

  • Natural - Properties appear in the same order that they were defined in the code
  • UsePropertySortAttributes - You can apply a SortPropsByAttribute to each property. This class takes an Integer as an argument for sorting

NOTE: The PropertyGrid View ToolBar Buttons (Categorized/Alphabetical) will always set the PropertySort to either CategorizedAlphabetical or Alphabetical. This overrides any sorting done with the property descriptors. To remedy this, add an event handler to the PropertySortChanged event and force the PropertySort to either Categorized or None.

DynamicPropWrapper Members
Namespace:DynamicProps

Wrap this class around your class object and point the PropertyGrid SelectedObject property to DynamicPropWrapper.DynamicDescriptor for dynamic property control.

Constructors

  • DynamicPropWrapper() - This constructor is only used if DynamicPropWrapper is inherited
  • DynamicPropWrapper(Object instance) - Always use this constructor when wrapping a class

Parameter NameTypeDescription
instanceObjectThe object whose properties are to be filtered

Methods

  • Object GetDefaultPropValue(String propName) - Returns the default value via the DynamicTypeDescriptor; this is the same value that the PropertyGrid will see when it asks for the DefaultValue.
  • Object GetPropValue(String propName) - Returns the property value via the DynamicTypeDescriptor; this is the same value that the PropertyGrid will see when it asks for the property value.

Properties

Property NameTypeAccessorsDescription
ItemDynPropertyOverrideGet/Set (default)Indexer for accessing the OverrideProps property
DynamicDescriptorDynamicTypeDescriptorGetReturns the DynamicDescriptor object that is used by PropertyGrid
InstanceObjectGet/SetAn instance of the class whose properties you want to dynamically filter/modify
OverridePropsDynPropertyOverrideListGetDictionary list of the class properties that are being overridden. Each dictionary item contains a list of the attributes that are being overridden. Use this property (or the indexer) to view and manipulate the dynamic property information
PropertySortTypeDynPropertySortTypesGet/SetChange the order in which properties are listed in the PropertyGrid

Points of Interest

Although it was never intended, you can also inherit the DynamicPropWrapper class and it automatically adjusts to provide type information for the object that inherited it. If you choose to use it this way, don't set the Instance property. This will force it back to a non-inherited mode and it will consequently get stuck in an infinite loop. Here are some other articles at The Code Project that have similar functionality:

History

  • 01-12-2008: DynamicProps 1.2.0
    • Bug fixed: setting the Instance property forces the sort order to default
  • 08-04-2007: DynamicProps 1.1.0
    • Bug fixed: DefaultValueObject would not work unless at least one override attribute was set
    • Additional documentation added to demo source code
  • 07-30-2007: DynamicProps 1.0.0
    • Initial release

License

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


Written By
Web Developer
United States United States
It started nearly 20 years ago. I was a BBS freak long before I could drive or even had a girl friend. I ran a type of software known at the time as Renegade; questionably a hacked version of another type of BBS software known as WWIV. Looking back I really had no choice. Renegade was free, fast and most importantly, open-source. Turbo Pascal was my flavor at the time, and I spent nearly all of my time with it; writing things from goofy SysOp pagers to label printing systems.

I'm a bit ashamed to say I can barely remember the basic "Pascal" syntax; I hear they call it Delphi or something now.. (lol)..

These days it's mainly all C#,C++/CLR syntax for me. And why not? That’s a powerful combination of rapid development, speed, compatibility, and flexibility. I'm sure most developers would agree that these days C# can't be beat for rapid development. It's powerful and even portable; a rare combination for a high-level language.

Language Experience: C#, C++/CLR, C, VB.NET, SQL, PHP, JavaScript, HTML, ASM

Comments and Discussions

 
GeneralMy vote of 5 Pin
Paul Wainwright24-Jan-11 2:07
Paul Wainwright24-Jan-11 2:07 
Generalgetting properties Pin
yura19894-Nov-09 2:35
yura19894-Nov-09 2:35 
QuestionChanging display of complex properties? Pin
Yumashin Alex2-Apr-08 6:59
Yumashin Alex2-Apr-08 6:59 

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.