Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

DSL Modelling - Implementing drop-down Properties

5.00/5 (2 votes)
4 Nov 2015CPOL2 min read 7.7K  
Extending your DSL model to restrict the values that can be selected for a property from a drop-down list

Introduction

When designing a model using a domain specific language and the Visual Studio DSL modeling SDK, we sometimes want to restrict the possible values that can be selected by implementing a drop-down listbox interface in the Visual Studio designer.

Image 1

For example, in the above example, when we are setting the source property for the event property operation, we want to restrict it to the available properties of the actual event being handled.  

Creating a UITypeEditor

The drop down list is provided by creating a UITypeEditor derived class in exactly the same way as you would do to have a drop-down list appear in the Windows Forms designer for a property of a control.  

This class needs to indicate that it will be providing a drop down list as its UI method, and it needs to create and populate the combo box accordingly.

C#
    public sealed class ProjectionPropertyOperationSourceFieldUITypeEditor
        : UITypeEditor 
    {

        private IWindowsFormsEditorService _editorService;

        /// <summary>
        /// Editor type for this property is a drop down list
        /// </summary>
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
        {
            if (null != context)
            {
                return UITypeEditorEditStyle.DropDown;
            }
            else
            {
                return base.GetEditStyle(context);
            }
        }

        public override object EditValue(ITypeDescriptorContext context, 
						IServiceProvider provider, object value)
        {
            if ((null != context) && (null != provider))
            {
                _editorService = (IWindowsFormsEditorService)provider.GetService
						(typeof(IWindowsFormsEditorService));

                ProjectionEventPropertyOperation pepo = null;
                // Note - context.Instance may be either a DSL shape or the underlying domain class
                // so if we add a shape we need to look up the underlying domain class here
                pepo = context.Instance as ProjectionEventPropertyOperation;
                if (null != pepo)
                {
                    // Create a listbox to hold all the event names in the parent projection
                    ListBox lb = new ListBox();
                    lb.SelectionMode = SelectionMode.One;
                    lb.SelectedValueChanged += OnListBoxSelectedValueChanged;

                    // Add an Empty item
                    lb.Items.Add("");

                    if (null != pepo.SelectedEvent)
                    {
                        foreach (var prop in pepo.SelectedEvent.EventProperties)
                        {
                            lb.Items.Add(prop.Name);
                        }
                    }

                    _editorService.DropDownControl(lb);
                    if (lb.SelectedItem == null) // no selection, return the passed-in value as is
                        return value;

                    return lb.SelectedItem;
                }
            }
            return base.EditValue(context, provider, value);
        }

        private void OnListBoxSelectedValueChanged(object sender, EventArgs e)
        {
            if (null != _editorService)
            {
                // close the drop down as soon as something is clicked
                _editorService.CloseDropDown();
            }
        }
    }
}

Obviously, how you populate the drop down list will depend on your own DSL model's requirements.

Attaching the Editor to the Property

The first step is to find the domain property that you want to have a drop-down list of options and click on the "Custom Attributes" button.

Image 2

This will bring up an interface to allow you to attach attributes to the property that will be automatically generated for this domain property.

In the resulting pop up dialog window, add an attribute name "System.ComponentModel.Editor".

Image 3

Then, add a parameter being the type of your custom created UITypeEditor derived class and a parameter being the type System.Drawing.Design.UITypeEditor.

From the IDE "Build" menu, select "Transform all T4 templates" and then "Rebuild All" - your auto generated code will now be decorated with the UITypeEditor required to add the drop down menu to the design time experience of that domain property. 

Points of Interest

The class that implements UITypeEditor has to be in the same project (.dll) as your DSL model.

History

  • 2015-11-04: Created

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)