Choosing WPF Property Grid editors from code
We had a question from a customer recently about how, in the WPF Property Grid, to choose an editor at runtime using code, rather than declaring it once and for all in the XAML. An example might be that only certain users are allowed to edit certain properties: it would be nice to display these properties as read-only to unauthorised users, so that they don’t try to edit them and get “punished” with an error message.
There are a couple of ways to do this, and I thought it might be interesting to share them. Perhaps the simplest and most basic is just to assign the editor in code rather than in the XAML:
DataTemplate template = (DataTemplate)(FindResource(PropertyGrid.ReadOnlyDisplayKey)); if (Environment.UserName == "Ivan") { template = (DataTemplate)(FindResource(PropertyGrid.SimpleTextEditorKey)); } PropertyEditor editor = new PropertyEditor(); editor.DeclaringType = typeof(Person); editor.PropertyName = "Surname"; editor.EditorTemplate = template; pg.Editors.Add(editor);
The only trick here is the use of FindResource to refer to the editor templates (whether built-in or custom).
This works fine, but it’s not idiomatic WPF, because the choice of UI is bundled up with the authorisation code in the code-behind, rather than expressed in the XAML. (Of course, refactoring the code would improve this, but it still leaves you with the situation that someone looking at the XAML won’t see that the Surname property has a PropertyEditor associated with it.) Can we find a more XAML-friendly approach?
Dynamism in WPF templates is achievable in two main ways: triggers and selectors. In this example, it’s probably okay to use a selector, because the user’s authorisation status is unlikely to change while the grid is up. (This assumption might fail if, for example, a supervisor could temporarily authorise the user to make changes by typing in a manager password. But let’s not worry about that.) The selector is easy to write:
public class DynamicTemplateSelector : DataTemplateSelector { public DataTemplate EditableTemplate { get; set; } public DataTemplate ReadOnlyTemplate { get; set; } public override DataTemplate SelectTemplate(object item, DependencyObject container) { // pretend this is impenetrable security code if (Environment.UserName == "Ivan") { return EditableTemplate; } else { return ReadOnlyTemplate; } } }
and easy to declare in the Window.Resources section:
<local:DynamicTemplateSelector
x:Key="DynamicTemplateSelector"
EditableTemplate="{StaticResource {x:Static ms:PropertyGrid.SimpleTextEditorKey}}"
ReadOnlyTemplate="{StaticResource {x:Static ms:PropertyGrid.ReadOnlyDisplayKey}}"
/>To put our DataTemplateSelector to work, we need an element that understands template selection. ContentControl is the element that allows us to present objects using data templates without introducing any UI of its own, so we’ll use that:
<DataTemplate x:Key="DynamicTemplate"> <ContentControl Content="{Binding}" ContentTemplateSelector="{StaticResource DynamicTemplateSelector}" /> </DataTemplate>
Note that the Content property is set to {Binding}, not to the more usual Value. This is because whichever template gets selected by the selector will be looking for the Value property on whatever it gets given, so we don’t need to (in fact, mustn’t) extract the Value ourselves.
Finally, we can now assign this template to the properties we want to mark as read-only to selected users:
<ms:PropertyGrid.Editors> <ms:PropertyEditor PropertyName="FirstName" EditorTemplate="{StaticResource DynamicTemplate}" /> </ms:PropertyGrid.Editors>
The property grid will now display the property as read-only or editable depending on the authorisation criteria in the selector.
In some situations, you could also use smart editors for this. For example, you could create a smart editor whose CanEdit implementation returns true if the user is not authorised. This could then be hooked up to the read-only template. By injecting this smart editor at the top of the editor chain, it would get first dibs on any properties the user wasn’t authorised to edit, while properties the user was authorised to edit would pass down the chain, presumably to find an appropriate read-write editor. The advantage of this approach is that you don’t need to specify individual properties; its disadvantages are that it is a very broad brush, and that it creates a nasty dependency on the order of editor declarations (see the smart editors post for why).
Needless to say, what we’ve shown here is no substitute for proper business layer logic in the underlying objects. If certain users shouldn’t be allowed to edit certain properties, then the business layer should check authorisation before allowing a change to take effect. What the above techniques do give us is a way to surface this business logic in the user interface, give users clear feedback about what they can and cannot do, and protect them from errors.
2 Responses to “Choosing WPF Property Grid editors from code”
Leave a Reply
![]()
BrainDump (1)
Community Code (1)
Events (6)
General (31)
Lab Samples (2)
LightSpeed (132)
MegaPack (3)
News (48)
Products (64)
Projects (4)
Screencast (6)
SharePoint (1)
Silverlight (5)
Silverlight Elements (12)
SimpleDB Management Tools (11)
Visual Studio (4)
VS File Explorer (5)
WPF (31)
WPF Diagramming (14)
WPF Elements (22)
WPF Property Grid (24)
![]()
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
December 2007
November 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007



Tagged as 

Posted by Ivan Towlson on 15 July 2008



Hi,
How to Create Toolbox and Properybox using WPF(C sharp)
I mean, I want to create a application that has a toolbox(listbox control) and drag the controls from toolbox and drop in the workspace(listbox control). Once we drop the controls in workspace, the properties related to that particular control should be displayed in property Panel(PropertyGrid control).Once we change the properties it should affect the workspace controls.(This Application like Visual studio toolbox and property box)
The Same Windows Application code is available in: http://www.devhood.com/tools/tool_details.aspx?tool_id=662
Thanks,
S.S.Sivaprasad
You can implement drag and drop by handling the MouseDown event and calling the DragDrop.DoDragDrop method. Your destination (the workspace) must have AllowDrop=”True” and handle the Drop event.
You can then set the SelectedObject property of the property grid to be the control instance in the workspace (depending on your implementation you will probably be able to just databind PropertyGrid.SelectedObject to Workspace.SelectedItem). You can get a trial version of the property grid from http://www.mindscape.co.nz/Products/WpfPropertyGrid/download.aspx.