I really like the api exposed by the original PropertyGrid which I have been using for years now but it's a Winforms control. This presents some problems. The main issue for me with the Winforms version of the PropertyGrid is that it's not styleable. So it means that I'll have some inconsistency in my UI and it will stick out as shabby and odd.
Below is a screenshot of the PropertyGrid bound to a simple “Person” object, that exposes a complex type Address and a vehicle collection property.
As old as it may look, it works so well and does it job so nicely! I love this control. In the end, I've decided to use this in my Wpf application regardless of the oddity it brings. Clearly, functionality is a lot more important and since beauty lies in the eyes of the beholder, it's a subjective matter. And writing a brand new native Wpf PropertyGrid control is out of the question.
Looks apart, think of the great things this control can do. You practically bind your objects to it and it will list them in a neat grid, categorized, with many builtin editors for color editing, navigating for images, browsing and editing collections using the builtin CollectionEditor etc. And if this is not enough you can write simple extensions with your own custom editors. Indeed this control is a gem!
Update 4/30/2011
It seems since we are referencing a Winforms library, in particular System.Windows.Forms, our client app is forced to reference the fatter .NET 4.0 version versus just the slimmer .NET 4.0 client profile which is the default.
It's not such a big con, but most certainly something to consider. I've left some more instructions at the bottom of this post.One thing in particular that I've done is to wrap it up in a Custom Wpf Control because in order to use the Winforms version in Wpf, we'll need to :
- Interop via WindowsFormsHost (as easy as eating cake)
- We'd like to bind our ViewModel to the PropertyGrid directly from the View declaratively. This will allow us to avoid tight coupling with our ViewModel.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfLab2.Controls" xmlns:o="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"> <Style TargetType="{x:Type local:WpfPropertyGrid}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:WpfPropertyGrid}"> <Grid> <WindowsFormsHost x:Name="host"> <o:PropertyGrid x:Name="propertyGrid1"/> </WindowsFormsHost> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
Minus the namespaces and the common style declarations you'll likely do for any templating requirement, it's fairly simple. All we need is to nest the Winforms PropertyGrid inside a WindowsFormsHost.
<Grid> <WindowsFormsHost x:Name="host"> <o:PropertyGrid x:Name="propertyGrid1"/> </WindowsFormsHost> </Grid>
That's pretty much all of the code. Simple indeed. The Wpf Control itself consists of a single dependency property minus a small plumbing effort. Attached to this article I include a sample application containing the control, so you can get a hang of how it works. Our View itself that consumes the PropertyGrid, just comes down to a single line of code that includes the Custom control binding to a property in the ViewModel declaratively eg:
<local:WpfPropertyGrid SelectedObject="{Binding PersonItem, Mode=TwoWay}" />
See! Now powered with such a fantastic control you can provide easy editing of objects in your application and maintain your MVVM pattern. I love it.
Make sure you also read the following resource on msdn if your new to the PropertyGrid. It provides all the basics you'll need to know to get you up and running quickly.
http://msdn.microsoft.com/en-us/library/aa302326.aspx (Basics about the PropertyGrid)
http://msdn.microsoft.com/en-us/library/ms742875.aspx (About hosting winforms in wpf)
The sample application included is a basic example using a single person object that in turn has a complex property and a collection property. Once you edit the properties and hit the Ok button, it will display the changes in the object via a messagebox.
Nothing fancy, but you can see some simple mvvm, creation of a simple custom value converter for the complex type “Address” exposed as a property and a the creation of a simple collection editor to allow editing the “Vehicles” collection property. Just enough to get you started.
Update: 4/30/2011
A gotcha I forgot to mention is that you'll have to reference System.Windows.Forms which resides in the System.Windows.Forms assembly. The PropertyGrid control resides in this dll. When trying to reference this library from the project references dialog, you won't find it in the list of available dlls. That's because by default your project is using the .Net 4.0 client profile, so go in your project properties window and change it from .Net 4.0 client profile to .Net 4.0. After this step you can try referencing the dll again and it will be in the list.
The Microsoft .NET Framework 4 Client Profile provides a subset of features from the .NET Framework 4. The Client Profile is designed to run client applications and to enable the fastest possible deployment for Windows Presentation Foundation (WPF) and Windows Forms technology. Application developers who require features that are not included in the Client Profile should target the full .NET Framework 4 instead of the Client Profile.Update: 5/25/2011
I was able to change the target framework back to the default Client profile after referencing System.Windows.Forms ; It seems this is already in the Client profile. What will throw you off is if your referencing System.Design.dll which will require the Full version of .NET. One typical requirement will arise for you when developing custom TypeEditors because most of the existing type editors are in the System.Design dll. Still thankfully, my needs for custom type editors was pretty basic and I got away developing one from scratch ( inheriting TypeEditor).
I found that not setting height and width explicitly for the control makes its load time slow and at most awkward even. The fix is to be explicit with the height and width. This must be due to layout differences between WPF and Windows Forms. The following article on msdn has the meat and potatoes.
http://msdn.microsoft.com/en-us/library/ms744952.aspx
So, in case its not clear, when using the control, this is what you want to attempt :
<my:WpfPropertyGrid SelectedObject="{Binding PersonItem}" Width="290" Height="350"> </my:WpfPropertyGrid>
Notice the explicit Width and Height above. Now the speed should be super fast! Keep reading the article on msdn I link to above, it has some pretty good information.
And a small correction to the article, it's not entirely true that you cannot style the property grid. You can do some basic styling of the Winforms PropertyGrid. What you cannot do is enjoy a complete designer experience like you can currently with WPF controls. So, it's not as traggic as I made it sound.