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:
mTestObject = new DemoClass1;
mDynPropWrapper = new DynamicPropWrapper(mTestObject);
propertyGrid1.SelectedObject = mDynPropWrapper.DynamicDescriptor;
Overriding Attributes
Overriding a property attribute can be done with one line of code:
mDynPropWrapper["MyPropertyName"].Overrides.Replace_
(new DefaultValueAttribute("New Default Value"));
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:
- By overriding the default values for each property - see the example above
- By using a global
DefaultValueObject for all property default values - see the example below
mTestObject = new DemoClass1;
mTestObject_Defaults = new DemoClass1();
mDynPropWrapper = new DynamicPropWrapper(mTestObject);
mDynPropWrapper.OverrideProps.DefaultValueObject = mTestObject_Defaults;
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 Name |
Type |
Description |
instance |
Object |
The 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 Name |
Type |
Accessors |
Description |
Item |
DynPropertyOverride |
Get/Set (default) |
Indexer for accessing the OverrideProps property |
DynamicDescriptor |
DynamicTypeDescriptor |
Get |
Returns the DynamicDescriptor object that is used by PropertyGrid |
Instance |
Object |
Get/Set |
An instance of the class whose properties you want to dynamically filter/modify |
OverrideProps |
DynPropertyOverrideList |
Get |
Dictionary 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 |
PropertySortType |
DynPropertySortTypes |
Get/Set |
Change 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