Sometimes when defining a property for a domain model element you may need to use a complex type that has more than one property or can’t easily be displayed using a single text field or drop down in the property editor. A good example might be a class that holds a list of strings for a GUI interface or a Rich Text editor for a custom text field required by your framework.
To resolve this you can create a custom editor and hook it into your domain model that will provide a proper user interface to specify information for your property.
There are three steps you need to take in order to wire your domain property to display a custom editor:
1. Create a class derived from System.Drawing.Design.UITypeEditor that will launch the custom dialog box as below:
1:
2: using System;
3: using System.Collections.Generic;
4: using System.Text;
5:
6: // Need to add a reference to System.Drawing DLL.
7: using System.Drawing.Design;
8: using System.Security.Permissions;
9: using Microsoft.VisualStudio.Modeling;
10: using Microsoft.VisualStudio.Modeling.Design;
11:
12: namespace XXX.UIProcessDesigner.UIEditors
13: {
14:
15: // FxCop rule: must have same security demands as parent class
16: [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust"),
17: PermissionSet(SecurityAction.InheritanceDemand, Name = "FullTrust")]
18: public class FormPromptUITypeEditor : System.Drawing.Design.UITypeEditor
19: {
20:
21: /// <summary>
22: /// Overridden to specify that our editor is a modal form
23: /// </summary>
24: /// <param name="context"></param>
25: /// <returns></returns>
26: public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
27: {
28: return UITypeEditorEditStyle.Modal;
29: }
30:
31:
32: /// <summary>
33: /// Called by VS whenever the user clicks on the ellipsis in the
34: /// properties window for a property to which this editor is linked.
35: /// </summary>
36: /// <param name="context"></param>
37: /// <param name="provider"></param>
38: /// <param name="value"></param>
39: /// <returns></returns>
40: public override object EditValue(
41: System.ComponentModel.ITypeDescriptorContext context,
42: IServiceProvider provider,
43: object value)
44: {
45:
46: // Get a reference to the underlying property element
47: ElementPropertyDescriptor descriptor = context.PropertyDescriptor as ElementPropertyDescriptor;
48: ModelElement underlyingModelElent = descriptor.ModelElement;
49:
50: // context.Instance also returns a model element, but this will either
51: // be the shape representing the underlying element (if you selected
52: // the element via the design surface), or the underlying element
53: // itself (if you selected the element via the model explorer)
54: ModelElement element = context.Instance as ModelElement;
55:
56: FormPromptUITypeEditorForm theForm = new FormPromptUITypeEditorForm();
57:
58: theForm.Value = (string)value;
59:
60: if (theForm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
61: {
62: value = theForm.Value;
63: }
64:
65: return value;
66: }
67:
68: }
69:
70: }
71:
72:
2. Create a Windows Form dialog that will be displayed when the editor is invoked, such as the one below:
3. Set the Custom Attributes for the Domain Property to reference the UITypeEditor class you have created.
The text is as follows: [System.ComponentModel.Editor(typeof(XXX.UIProcessDesigner.UIEditors.FormActionTypeUITypeEditor),typeof(System.Drawing.Design.UITypeEditor))]
The bold faced text is the full namespace of your class that derives from UITypeEditor.
I normally store all code that I add to a DSL Designer in various folders such as; CustomCode, UIEditors, Validators, etc. That way it is easy to find when I am trying to reference it.
Also, you can debug the UITypeEditor and Dialog by setting breakpoints in the code before you start debugging.