PropertyGrid, Custom Editors, MVVM (separation of concerns)

Jan 14, 2013 at 9:12 AM

Hi,

I am creating a "settings editor" that is supposed to support several type of settings classes.

The setting classes have some common interface but in general include different properties that the user should be able to edit. They are defined in different project (DLLs).

The editor consists of a simple form that has a PropertyGrid and some load buttons so the user can select a settings file and load it. The settings are then loaded into one of the classes and bound to the PropertyGrid.

My problem arises when I want to support custom editors for some of the properties. For example, I want a browse folder or browse file for some of the string properties.

I have seen the various extension options for custom editors but in order to use them I will have to violate some design constraints:

  • DataTemplate: If I use a data template it means I need to know in advance the name of the properties that need to have the custom editors - this is not so good since I want to support various classes of settings
  • Attributes: if I set an attribute in the settings class I create some dependancy between the settings class and the UI (editor). The minimum is a dependancy on the WPF toolkit (existing editors) but also, on the custom editor(s) I might want to create and should not be defined along with the setting class' project (since the custom editor is UI and the settings class is part of the Model)

Is there a way to use custom editors without knowing in advance which properties to use and still keeping the settings classes clean (I don't mind defining a new type of attribute that will "hint" to the PropertyGrid what custom editor to use, but not creating a direct dependancy between them).

 

 

Jan 14, 2013 at 1:25 PM

Interesting point.

First, I just to be sure I understand.

UI side, You can't specify which property use which editor since you want to stay "generic" or "flexible" on the various Models class that my be specified.

Model side, you can specify which property use which editor but you don't want to refer to UI specific classes.

 

The "EditorProperty" has a constructor that accept 2 strings. Use the "AssemblyQualifiedName" of your editor for both of them.

Ex.:

 

const string FirstNameEditorString = "Samples.Modules.PropertyGrid.Views.FirstNameEditor, Samples.Modules.PropertyGrid";

..

[Editor( FirstNameEditorString, FirstNameEditorString )]

 

It should do the trick.

Jan 14, 2013 at 1:56 PM

Hi emartin,

Thanks for the quick reply.

You got the situation right and I missed the constructor that takes the string arguments as you suggested and should solve the issues.

This solution though seems to be not type (or typos ;-) safe - In case the Editor (UI) assembly has change I will have to re-decorate and re-compile my external class (Model).

 Also, while it does not create actual dependency on the UI dll, the fully qualified type name is a little ugly.

 It would have been nice to be able to decorate the properties of a class with some “generic” attribute and then have the PropertyGrid find it according to that attribute

 e.g. in MyClass (in MyProject.Model.dll)

 

[PropertyCategoryType("File Path")
public string MyProperty { get; set; }

 

 then in the XAML (MyProject.View.dll)

 

<xctk:EditorDefinition CategoryType="File Path">
     <!-- other markup for settings the definition -->
</xctk:EditorDefinition>

 

 This way, the whole solution is more resilient to change, flexible and keeps things completely separate…

 

 

Jan 14, 2013 at 3:49 PM
Edited Jan 14, 2013 at 3:50 PM

Yes, I understand your point and the disadvantages of the "recompilation" problem. 

Since the "TypeName" approach was the one used by the standard WinForm PropertyGrid I think it should be OK for most of the user cases.

For the v1.8 and upcomming v1.9 (this week), I have no simple solution for you. The version 2.0 will have some PropertyItem generation handling points (protected method and/or event) that will allow you to control various properties of the PropertyItem (including the "Editor" property) during the generation process, but for now, the only Idea I have in mind is some kind of an hack I haven't tried :

The Editor type specified by the EditorAttribute is resolve using the "Type.GetType()" call.

The underlying mechanism of this call is suppose to rise the "AppDomain.AssemblyResolve" and "AppDomain.TypeResolve" events that allow you to control "string to type" convertion. If this is the case, you would may be able pass some "custom id" instead of a specific AssemblyQualifiedName as a type name to the EditorAttribute and do your own "string to type" convertion in theses events.