I wrote previously about editing custom types in the WPF Property Grid — how to extend the grid to provide a good editing experience for, say, PhoneNumber objects. But what if you have a particular property which is of a “known” type, but the normal editing experience isn’t appropriate?
Here’s an example. Suppose you have a PrintSettings class with an Orientation property of boolean type. That’s an awful API for you to have to deal with, and even worse for your users:
Quick, does an Orientation of true mean portrait or landscape? Who knows? Even if the designer of the PrintSettings class had used an enum instead of a boolean, you might still want to improve the editing experience by providing pictures as well as the words Portrait and Landscape, so that less print-savvy users would know what the terms meant.
Unfortunately, the type editor extensibility mechanism doesn’t help us in this case. We don’t want to change the editor used for booleans in general, because that would affect the Duplex editor as well: we just want to change it for this specific property.
In the WPF Property Grid, we can do this using property editors. You create property editors in almost exactly the same way as type editors, but they have to be wired up a little differently.
To create our custom property editor, just as with a type editor, all we have to do is create a DataTemplate which can bind to a boolean value:
<DataTemplate x:Key="OrientationEditor"> <ComboBox SelectedValue="{Binding Value}" SelectedValuePath="Tag" BorderThickness="0"> <ComboBoxItem Tag="False"> <StackPanel Orientation="Horizontal"> <Border Width="30" Height="30"> <Rectangle Width="17" Height="22" Stroke="Black" StrokeThickness="1" Fill="LightGray" /> </Border> <TextBlock Text="Portrait" VerticalAlignment="Center" /> </StackPanel> </ComboBoxItem> <ComboBoxItem Tag="True"> <StackPanel Orientation="Horizontal"> <Border Width="30" Height="30"> <Rectangle Width="22" Height="17" Stroke="Black" StrokeThickness="1" Fill="LightGray" /> </Border> <TextBlock Text="Landscape" VerticalAlignment="Center" /> </StackPanel> </ComboBoxItem> </ComboBox> </DataTemplate> |
Here’s the first difference from the type editor. In the type editor template, we bound our databound elements to properties of the edited type. (In the PhoneNumber example, we had a text box bound to the CountryCode property.) But a boolean doesn’t have properties. How, then, can we reference it in our DataTemplate? The WPF Property Grid solves this by requiring property editors operating on base types to instead bind to a special pseudo-property called Value. The property grid wires things up so that the Value pseudo-property actually maps to the real property, in this case Orientation.
Now, as we did with our type editor, we have to tell the WPF Property Grid to use this template for editing the PrintSettings.Orientation property. We do this by adding a PropertyEditor declaration to the grid’s Editors property:
<ms:PropertyGrid SelectedObject="{Binding}"> <ms:PropertyGrid.Editors> <ms:PropertyEditor DeclaringType="local:PrintSettings" PropertyName="Orientation" EditorTemplate="{StaticResource OrientationEditor}" /> </ms:PropertyGrid.Editors> </ms:PropertyGrid> |
Note the DeclaringType and PropertyName declarations to tell the WPF Property Grid where to use the new editor.
After adding the new editor, the grid looks like this:
Now that’s a lot more meaningful!