How to obtain ITypeDescriptorContext and IServiceProvider in inherited ControlDesigner class
Asked Answered
M

2

6

I have inherited ControlDesigner class into MyControlDesigner.

In this class I need to obtain objects behind ITypeDescriptorContext and IServiceProvider interfaces, but I don't know how :(

I need these 2 interfaces to pass them in method, but I can't find them inside any other object.

Can somebody please help me.

Thank you

Best regards Bojan

Mancunian answered 26/1, 2011 at 23:40 Comment(1)
It's an old question and probably you don't need the answer anymore, but future readers may find my answer below useful.Hutchison
H
5

There is an internal class EditorServiceContext in System.Design assembly which has implemented ITypeDescriptorContext, IServiceProvider and IWindowsFormsEditorService.

You can find it and create an instance of the class or use its static methods to satisfy your requirement. For example to show the editor for a property, you can use it this way:

var editorServiceContext = typeof(ControlDesigner).Assembly.GetTypes()
    .Where(x => x.Name == "EditorServiceContext").FirstOrDefault();
var editValue = editorServiceContext.GetMethod("EditValue",
    System.Reflection.BindingFlags.Static |
    System.Reflection.BindingFlags.Public);
editValue.Invoke(null, new object[] { this, this.Component, "The Property Name" });

If for any reason you need the source of the class to apply some changes to it, here is the code for that class:

using System;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;

internal class EditorServiceContext : 
    IWindowsFormsEditorService, ITypeDescriptorContext, IServiceProvider
{
    // Fields
    private IComponentChangeService _componentChangeSvc;
    private ComponentDesigner _designer;
    private PropertyDescriptor _targetProperty;

    // Methods
    internal EditorServiceContext(ComponentDesigner designer)
    {
        this._designer = designer;
    }

    internal EditorServiceContext(ComponentDesigner designer, PropertyDescriptor prop)
    {
        this._designer = designer;
        this._targetProperty = prop;
        if (prop == null)
        {
            prop = TypeDescriptor.GetDefaultProperty(designer.Component);
            if ((prop != null) && typeof(ICollection).IsAssignableFrom(prop.PropertyType))
            {
                this._targetProperty = prop;
            }
        }
    }

    internal EditorServiceContext(ComponentDesigner designer, PropertyDescriptor prop, string newVerbText) : this(designer, prop)
    {
        this._designer.Verbs.Add(new DesignerVerb(newVerbText, new EventHandler(this.OnEditItems)));
    }

    public static object EditValue(ComponentDesigner designer, object objectToChange, string propName)
    {
        PropertyDescriptor prop = TypeDescriptor.GetProperties(objectToChange)[propName];
        EditorServiceContext context = new EditorServiceContext(designer, prop);
        object obj2 = prop.GetValue(objectToChange);
        object obj3 = (prop.GetEditor(typeof(UITypeEditor)) as UITypeEditor).EditValue(context, context, obj2);
        if (obj3 != obj2)
        {
            try
            {
                prop.SetValue(objectToChange, obj3);
            }
            catch (CheckoutException)
            {
            }
        }
        return obj3;
    }

    private void OnEditItems(object sender, EventArgs e)
    {
        object component = this._targetProperty.GetValue(this._designer.Component);
        if (component != null)
        {
            CollectionEditor editor = TypeDescriptor.GetEditor(component, typeof(UITypeEditor)) as CollectionEditor;
            if (editor != null)
            {
                editor.EditValue(this, this, component);
            }
        }
    }

    void ITypeDescriptorContext.OnComponentChanged()
    {
        this.ChangeService.OnComponentChanged(this._designer.Component, this._targetProperty, null, null);
    }

    bool ITypeDescriptorContext.OnComponentChanging()
    {
        try
        {
            this.ChangeService.OnComponentChanging(this._designer.Component, this._targetProperty);
        }
        catch (CheckoutException exception1)
        {
            if (exception1 != CheckoutException.Canceled)
            {
                throw;
            }
            return false;
        }
        return true;
    }

    object IServiceProvider.GetService(Type serviceType)
    {
        if ((serviceType == typeof(ITypeDescriptorContext)) || (serviceType == typeof(IWindowsFormsEditorService)))
        {
            return this;
        }
        if ((this._designer.Component != null) && (this._designer.Component.Site != null))
        {
            return this._designer.Component.Site.GetService(serviceType);
        }
        return null;
    }

    void IWindowsFormsEditorService.CloseDropDown()
    {
    }

    void IWindowsFormsEditorService.DropDownControl(Control control)
    {
    }

    DialogResult IWindowsFormsEditorService.ShowDialog(Form dialog)
    {
        IUIService service = (IUIService)((IServiceProvider)this).GetService(typeof(IUIService));
        if (service != null)
        {
            return service.ShowDialog(dialog);
        }
        return dialog.ShowDialog(this._designer.Component as IWin32Window);
    }

    // Properties
    private IComponentChangeService ChangeService
    {
        get
        {
            if (this._componentChangeSvc == null)
            {
                this._componentChangeSvc = (IComponentChangeService)((IServiceProvider)this).GetService(typeof(IComponentChangeService));
            }
            return this._componentChangeSvc;
        }
    }

    IContainer ITypeDescriptorContext.Container
    {
        get
        {
            if (this._designer.Component.Site != null)
            {
                return this._designer.Component.Site.Container;
            }
            return null;
        }
    }

    object ITypeDescriptorContext.Instance
    {
        get
        {
            return this._designer.Component;
        }
    }

    PropertyDescriptor ITypeDescriptorContext.PropertyDescriptor
    {
        get
        {
            return this._targetProperty;
        }
    }
}
Hutchison answered 7/5, 2017 at 1:48 Comment(1)
I've tested the class for this example. Also a I've implemented a lighter version for this one and this one.Hutchison
W
1

Component.Site implements IServiceProvider, IDK about ITypeDescriptorContext, i'm looking for it too...

To get IServiceProvider you can do: var sp = (IServiceProvider)Component.Site;

Wylde answered 13/3, 2011 at 3:27 Comment(2)
Thank you for your answer, it work. I will continue to searching for ITypeDescriptorContext. If I find it, I will write it here. Thanks again.Mancunian
It's an old question and probably you don't need the answer anymore, but future readers may find my answer below useful.Hutchison

© 2022 - 2024 — McMap. All rights reserved.