About a week ago I found a very interesting implementation of a simple WPF PropertyGrid control at
CodePlex. It inspired me writing my own vision of PropertyGrid that could help me within my projects. Special thanks to
Robby Ingebretsen who gave me permissions using
Kaxaml controls styles and a couple of classes within this article. First thing you should always keep in mind is that with WPF the GDI age is over. You don't need drawing and rendering everything from code. This brings out that something like PropertyGrid control is now nothing more but a collection of brushes, data templates and the most simple steps to introduce the desired layout. It might take about 5 or 6 hours implementing the same control from scratch assuming you already have styles/themes for the controls. I won't describe the code line by line and would rather prefer concentrating on key aspects of the implementation. Complete sources and demo application can be found at my SkyDrive at the end of this article.
Final results. Demo application. 
The Property grid control is implemented in a full isolation inside a separate custom control library. This means that all control styles and effects are fully encapsulated within the control assembly and so do not impact the final application design. All you need is to add a reference to the property grid assembly and declare something like the following [MARKUP CUT]
<GridSplitter Width="2" Background="Black" /> <pg:PropertyGrid xmlns:pg="clr-namespace
enisVuyka.Controls.PropertyGrid;assembly=DenisVuyka.Controls.PropertyGrid" Grid.Column="1" SelectedObject="{Binding ElementName=button}" ShowAttachedProperties="False" ShowReadOnlyProperties="False" ExpandCategories="False"/>[MARKUP CUT] The PropertyGrid is presented by a customized System.Windows.Controls.Control class and alongside the native properties defines only four property grid related properties for the moment. They are: 1.
SelectedObject (object): Same as for the canonical Windows Forms PropertyGrid. It is an instance of an object the properties are to be changed for. 2.
ShowAttachedProperties (true/false): Defines whether to show attached properties. Though this version is not capable of maintaining attached properties properly (still working on it) the control is capable of displaying them visually. The default is "False". 3.
ShowReadOnlyProperties (true/false): Defines whether to show dependency properties that are readonly so having only getters. You won't be able to edit them but simply to see the values. For experimental purposes you can switch it on to see that readonly checkboxes will be properly reacting on such readonly properties like the "IsMouseOver". The default is "False". 4.
ExpandCategories (true/false): Defines whether categories should be expanded upon control load. I personally like it to be initially collapsed but nevertheless set the default value to "True". So by default all the categories will be expanded. Usually I guess the only "SelectedObject" definition/binding will be enough for everyday usage. You can omit the rest of the properties and rely on the default values.
UI features 1. PropertyGrid control Supports only one "Black" color scheme for the the moment. After having estimated the time required to duplicate the Blend or Kaxaml color scheme I've decided to reuse the existing wonderful implementation and got
Kaxaml permission for the styles, component templates and a couple of classes that I needed to change a bit according to my needs. Though everything I reused was reviewed, refactored and changed I still consider
Kaxaml set to be the most awesome set of the control templates that can be found today. The Control can be stretched within your panels without having any hardcoded width or height. For demo application I've used the common Grid layout with a vertical splitter between property grid and playground content so to see how it can be stretched in case property names are too long to be fully displayed.
2. Categories Categories are smooth and animated

It cannot be demonstrated by screenshots so you'll see that only after launching the demo application. Category templates are based on restyled Expander elements and so have their own Collaped/Expanded states unlike the Kaxaml approach within the TabControl where only one panel could be opened at a time.
3. UI Editors UI Editors are the heart of any PropertyGrid control. They have to be efficient and convenient enough for the user to change the values. All editors in this control are based on DataTemplates for CLR types, inherited/base types or user configured properties. This will be described further on.

All editors can be represented either by common controls or by user created ones. PropertyGrid performs re-templating and re-styling for the following set of common controls: 1. CheckBox 2. ComboBox 3. Expander 4. ScrollBar 5. ScrollViewer 6. Slider 7. TextBox 8. ToggleButton alongside with a couple of user defined custom editors for demo purposes (will be described further on). But these controls above take part in most of the editor templates. As I've mentioned earlier the property grid has the capability of choosing this or that editor according to the type of the property being edited. The key aspects and knowledge references will be given in the second half on the article. Now I'd like to dwell on the following features of the editor selection:
Default editor Among all the scope of properties and their editors there will always be situation when there's no UI editor defined. In this case the fallback UI is needed to display the property in any way and rely on Type Converters that might still define the property value converted from a string at some kind of TextBox element. So the default fallback editor here might possibly be a TextBox control. Thus I've tried covering different types of properties by relying on the default editor, like Width, Height, etc

All property value assignments are proxied by TypeConverters so in this case I can still have a valid property editor by means of the most basic Validation applied (I'm still working on more powerful validation and error notifications)

As for the existing editors the property grid control prioritize template selection based on CLR type. There's a set of already predefined ones but it is quite an easy thing importing them during runtime or extend the template selection factory (actually I'm also working on providing a service bus support with IServiceProvider/IServiceContainer but it's a point of future releases).
"Boolean" editor Boolean editors are represented by CheckBox elements. Among the rest I think this is the less error-prone approach possible.

This editor reflects the readonly/writable state of the property properly so you won't be able defining getter-only property values.
"Enum" editor Represented by a ComboBox element containing all the possible value for the corresponding enum-based property reflecting the values of the Enum.

Like the CheckBox editor this one neither allows user define error-prone values as the proper values are limited to a list. This editor is applied to all property types that are based on "
System.Enum" type. Alongside there are customized templates that provide more rich capabilities of editing property values:
ComboBox editor There are many properties that are not based on Enums but nevertheless have a fixed (or nearly fixed) set of options to be chosen by the end-user. Let's take Font Families for example. It can be regarded as a fixed set as the user defining the Font Family value will be obliged keeping the existing list of possible values rather that typing anything he wants. So in this case Font Family is not an Enum-based value but is a perfect candidate to be displayed as a ComboBox selector. The same goes for example for
FontStyle FontWeight, FontStretch, etc properties.

Meanwhile there might be, let's say, dual-oriented editors that support both either existing values or manual typing property value definition. The perfect sample for such a case might be a "
Brush"-based properties. There have always been a set of predefined or named colors developers could use and the possibilities for defining/constructing any color based on it's ARGB members. This means that "Brush" editor should support either named colors or manual definitions:
"Brush" editor 
The "Brush" editor is presented by an editable ComboBox that has a list of all Named colors (dynamically loaded) and yet is capable of converting user typed values from strings to appropriate brush instances where possible, the BrushConverter is used for this purpose. Also the combo is styled so that each Named color can be previewed before selection. The "Brushes" that don't belong to Named color family can be still displayed in the property grid in their native view.
"Thickness" editor The "Thickness" editor was the first attempt to demonstrate the user defined templates and how the Point or Thickness based property can be edited in a different way. So I've created a separate editor control having two editing possibilities: 1. Common default-based text control. It can take only one value so that it will be set to all four members.

2. Expandable area for editing each value member separately:

This is just one of the samples to get the idea that you can provide any UI you want to edit a common property.
"Opacity" editor Another feature of this PropertyGrid control is editor (template) selection based on named properties. I'm still working on a more efficient way of properties definition for that purpose but for present moment you don't need changing anything to the object type you are editing within the property grid. All required is to define an editor template with a name of the property that don't have any build in predefined editor. "
Opacity" property is a Double-based one. For all the doubles it comes out that the "Default" editor with an appropriate TypeConverter is quite enough to define a Double value. But there are many cases when the user can be restricted in the values he type. For example the "Opacity" takes a range between 0.0 and 1.0 as a valid value. So it is a perfect candidate for having a tuned editor for example looking like a Slider:

So you can get the most of a slider features like defining the Minimum/Maximum properties, TickFrequency, AutoToolTipPrecision, etc. and make this property editor less error-prone for the end-user as soon as you restrict the value setting possibilities only for a range of valid ones. Also I've implemented a custom "
Point" editor providing possibilities of editing parts of the Point structure similar to the "Thickness" editor and based on it another customization for "
RenderTransformOrigin" property.
"RenderTransformOrigin" editor RenderTransformOrigin property thus based on a
Point structure also has a valid range for each member of the structure. Same as the opacity both X and Y expect the range between 0.0 and 1.0 doubles so this property can also be tuned in order to be more safe and restrictive. I've again used the Slider approach here for demo purposes:

This is a composite editor that is presented by a
Default one to define the values manually and having Two sliders for each member of the Point structure. The editable part is automatically updated upon changing the slider values, hints and tooltips are also provided while dragging the slider. That's all as for the key UI editor aspects. More details you will get from the sources and demo project. Again, I have to mention that you can implement any sort of UI required to edit this or that value type and I find this very appealing for future enhancements. I'm still working on more complex editors and their dynamic integrations outside the property grid control.
Interopability and Windows Forms Until now I was mainly concentrated on Dependency Objects and editing Dependency Properties. It is quite easy to extend the control to provide Native properties support in future so that it can be used within any object instance. Demo application solution contains a Windows Forms project for interop capabilities demonstration where the PropertyGrid holds another instance of PropertyGrid control as a SelectedObject.
private void Form1_Load(
object sender,
EventArgs e){
this.elementHost1.Child =
new DenisVuyka.Controls.PropertyGrid.
PropertyGrid() { SelectedObject =
new DenisVuyka.Controls.PropertyGrid.
PropertyGrid() }; }This will look like the following:

So as I've said the Windows Forms support is on the way but not a difficult task to accomplish.
What are the key points and aspects you should get acquainted with in order to implement your own vision? Step 1. From property descriptor to business object. The main task of the property grid is displaying object properties and giving possibilities of changing their values in convenient way. So collecting properties is the first step do be thought over and performed. Each object to be displayed in a property grid has a set of public properties and each property has a special descriptor giving possibilities analyzing them from code. So you will have to implement a wrapper around each property encapsulating the process of value changing and ready to be bound to the UI elements as some business object. Each property can provide the following minimum set of properties to the UI elements: 1.
Name (mandatory). Each property has a name and this name should be displayed as a Label right before the value editor control. 2.
Category (optional). The properties can be grouped by different categories so that user can easily manipulate a set of properties belonging to some logical family. 3.
Type (mandatory). Property type describes the type of the value that is to be assigned for the instance of the object. This is the only way to choose the correct UI editor for each property. 4.
Value (mandatory). This is a what to be set by UI editors and to be passed to underlying editable object instance. 5.
IsReadOnly (optional). The property might occur to be read only (having only a getter) and so UI should react on that in a proper manner. So you might work out something similar to the following diagram:

Note that here and later on I'll be dealing with Dependency Properties only. I've reserved the Native properties and their maintenance for future enhancements and posts.
Property Category has only the "
Name" mandatory property and serve a container for property items. It might look like given below:

I've added additional optional boolean property called "
IsExpanded" just for visualization purposes. The property grid will have an option defining whether all the property categories should be collapsed or expanded by default. Here's the whole diagram for properties and related infrastructure

So upon setting the object to be edited your property grid control has to enumerate all the dependency properties and wrap them into some entities called here "
DependencyPropertyItem" that will be bound to UI elements for end users. You can get enumerate all property descriptors using the following snippet:
PropertyDescriptorCollection descriptors =
TypeDescriptor.GetProperties(component,
new Attribute[] {
new PropertyFilterAttribute(
PropertyFilterOptions.SetValues |
PropertyFilterOptions.UnsetValues |
PropertyFilterOptions.Valid) });Next thing you can get is extracting a
DependencyPropertyDescriptor from a common
PropertyDescriptor in the following way:
DependencyPropertyDescriptor dpDescriptor =
DependencyPropertyDescriptor.FromProperty(descriptor);It will give you possibilities getting the Dependency Property only related metadata like determining whether it is an Attached Property, adding the value change and coerce callbacks, getting default values, etc.
Step 2. From business object to data template Now as you already have some sort of business object it is time to start thinking of possible ways to display it in a proper way. Visually property grid displays a two-column grid where first column displays labels or text blocks identifying property names and second column displays different types of UI editors for setting values in a convenient way. This control will be using a plain custom Control where the whole layout and control template will be declared within XAML. To get the basic idea of data templates used within the property grid I'd recommend you referring to the following articles. Guess this will be more efficient than I will be copy-pasting information that is already clarified everywhere:
Data Templating Overview WPF DataBinding, Styling and DataTemplates How can I display time information more graphically in WPF Here it will be used a Control-based class templated in a way to expose ItemsControl. Something like the following:
<ItemsControl ItemsSource="{TemplateBinding local:PropertyGrid.Properties}" Background="<Some color>" />DataTemplate for each dependency property wrapper may look like the following snippet:
<DataTemplate DataType="{x:Type data:DependencyPropertyItem}"> <Grid Margin="4"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" Margin="0,0,8,0" TextAlignment="Right" VerticalAlignment="Center" Text="{Binding Mode=OneTime, Path=Name}" ToolTip="{Binding Mode=OneTime, Path=Name}"/> <ContentControl Grid.Column="1" VerticalAlignment="Center" Content="{Binding Mode=OneWay}" ContentTemplateSelector="{StaticResource propertyTemplateSelector}" /> </Grid></DataTemplate>Snippet above presents one common row in your property grid control. It is layouted as a two-column grid where column 1 will contain a TextBlock element bound to the "Name" property of the underlying business object. Column 2 will be presented as a dynamic ContentControl or "Value Editor". According to the property type it will be "replaced" to the proper UI element. To get more information on ContentControl and it's usage details you can refer to the following articles:
WPF Control Templates - An Overview Why WPF Rock... (The content model) Dr. WPF blog Choosing the proper UI editor I assume that at this moment you are already aware of templating the ItemsControl and providing basic data templates for the items. The next question that might arise from your side is how exactly the ContentControl is turned into the proper UI editor and how to create different types of editors for different property types. This is where you might need nested templating or data templates inside the data templates and this is when you need details on
ContentTemplateSelector property of a ContentControl or custom
DataTemplateSelector implementations. I've also prepared a couple of links to start digging from in case you hear these words for the first time:
"Routed Template Selection" by Josh Smith "How do I display items in an ItemsControl using different templates?" by Beatriz Costa As you've seen from the snippets above the
DependencyPropertyItem data template declares a ContentControl that has a
PropertyTemplateSelector assigned for the
ContentTemplateSelector property. It is a custom implementation of a DataTemplateSelector and it's job will be to get an appropriate DataTemplate for the UI editor according to the ItemsControl item being templated.
Step 3. UI Editors As soon as you can style ItemsControl and aware of DataTemplating the next task you'll have to perform is to implement as much UI editors as you want and give them any desirable view. You can think over having UI editor templates outside the control so having possibilities extending your external collections later on. For a set of sample predefined editors and control templates please refer to the "
/Themes/PropertyEditors.xaml" resource dictionary within the property grid control. This will give you all the required material and ideas needed to implement you own vision of value editors.
Conclusion: Of course, there are still plenty of tasks for me to finalize in order to produce a fully-fledged property grid control and there's a lot of stuff for anyone else to change or study. But with the appearance of WPF I think we have reached the point in time where we can actually implement all the requirements rather than thinking over how to do that. As I've mentioned several times across the article I will continue working on this project so you may expect to hear more news and get more updates here. So thanks for your attention and keep on the line...
Source code and demo application for the article Updated information: The PropertyGrid control described here moved to the CodePlex. All new information and updates can be found there.