Añadiendo Editor / EditorAttribute en tiempo de ejecución (dinámicamente) a la propiedad de un objeto

StackOverflow https://stackoverflow.com/questions/2043579

Pregunta

Cómo añadir el EditorAttribute (Editor) a la propiedad de un objeto en tiempo de ejecución?

Tengo My.Settings.ExcludeFiles, que es creado por el diseñador ajustes como Public Property ExcludedFiles() As Global.System.Collections.Specialized.StringCollection. Al editar ExcludedFiles a través de una rejilla de propiedades, la "Colección Editor de cadenas" genera un "Constructor del tipo 'System.String' no encontrado" en tiempo de ejecución es una excepción.

No puedo cambiar los atributos de la propiedad ExcludeFiles porque se sobrescribirán la próxima vez que se realicen cambios de configuración. Por lo tanto, debo adjuntar / añadir el Editor / EditorAttribute en tiempo de ejecución.

Lo que quiero hacer es añadir el StringCollectionEditor en tiempo de ejecución, que se muestra a continuación como atributo en tiempo de diseño.

    <Editor(GetType(StringCollectionEditor), GetType(UITypeEditor))> _

Soluciones

Método # 1

TypeDescriptor.AddAttributes( _
    GetType(Specialized.StringCollection), _
    New EditorAttribute( _
        "System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", _
         GetType(System.Drawing.Design.UITypeEditor)))

Sólo tiene que añadir este atributo la vez, como inicialización de la aplicación.

Método # 2

Más flexible. Ver Nicolas Cadilhac responder más adelante en Adición Editor / EditorAttribute en tiempo de ejecución (dinámicamente) a un objeto de propiedad. Utiliza las clases derivadas CustomTypeDescriptor y TypeDescriptionProvider. Sólo tiene que añadir el proveedor de una vez, tales como inicialización de la aplicación.

¿Fue útil?

Solución

Después de dar mi primera respuesta, recordé otra solución dada por Marc Gravell que incluso lo comenté. Lo creas o no, sólo tiene que llamar TypeDescriptor.AddAttributes ().

Este es aquí: ¿Cómo me inyecto una UITypeEditor personalizado para todas las propiedades de un tipo de código cerrado? .

En su caso se da:

TypeDescriptor.AddAttributes(
    typeof(StringCollection),
    new EditorAttribute("System.Windows.Forms.Design.StringCollectionEditor,
        System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
        typeof(UITypeEditor)))

Así que tal vez debería desmarcar mi respuesta anterior y confirmar ésta como la solución (aunque todo el mérito es de Marc). Pero mi post anterior todavía le da una buena técnica cuando lo que necesita hacer cosas más complejas con una TypeDescriptor.

Otros consejos

No se puede. Un atributo sólo puede definirse en tiempo de compilación (a menos que genere el tipo de forma dinámica, por supuesto)

Sí, es posible cambiar dinámicamente un TypeDescriptor para que devuelva el UITypeEditor desea. Esto se explica en este artículo . Pero tenga en cuenta que se añadirá a todas las propiedades de este tipo.

Agarré el código de aquí y más o menos cambié por lo siguiente:

private class StringCollectionTypeDescriptor : CustomTypeDescriptor
{
    private Type _objectType;
    private StringCollectionTypeDescriptionProvider _provider;

    public StringCollectionTypeDescriptor(
        StringCollectionTypeDescriptionProvider provider,
        ICustomTypeDescriptor descriptor, Type objectType)
        :
        base(descriptor)
    {
        if (provider == null) throw new ArgumentNullException("provider");
        if (descriptor == null)
            throw new ArgumentNullException("descriptor");
        if (objectType == null)
            throw new ArgumentNullException("objectType");
        _objectType = objectType;
        _provider = provider;
    }

    /* Here is your customization */
    public override object GetEditor(Type editorBaseType)
    {
        return new MultilineStringEditor();
    }
}

public class StringCollectionTypeDescriptionProvider : TypeDescriptionProvider
{
    private TypeDescriptionProvider _baseProvider;

    public StringCollectionTypeDescriptionProvider(Type t)
    {
        _baseProvider = TypeDescriptor.GetProvider(t);
    }

    public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
    {
        return new StringCollectionTypeDescriptor(this, _baseProvider.GetTypeDescriptor(objectType, instance), objectType);
    }
}

A continuación, se registra su proveedor:

TypeDescriptor.AddProvider(new StringCollectionTypeDescriptionProvider
    (typeof(System.Collections.Specialized.StringCollection)),
    typeof(System.Collections.Specialized.StringCollection));

Esto funciona bien, excepto que le hará descubrir que tiene otro problema: MultilineStringEditor es un editor que trabaja con el tipo String, no con el tipo StringCollection. Lo que realmente se necesita es la StringCollectionEditor privado en el marco .Net. Así que vamos a reemplazar GetEditor por:

public override object GetEditor(Type editorBaseType)
{
    Type t = Type.GetType("System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
    return TypeDescriptor.CreateInstance(null, t, new Type[] { typeof(Type) }, new object[] { typeof(string) });
}

Espero que esto ayude.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top