Adicionando editor / editorattribute em tempo de execução (dinamicamente) à propriedade de um objeto

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

Pergunta

Como adicionar o editorattribute (editor) à propriedade de um objeto em tempo de execução?

Eu tenho My.Settings.ExcludeFiles, que é criado pelo designer de configurações como Public Property ExcludedFiles() As Global.System.Collections.Specialized.StringCollection. Ao editar ExcludedFiles Por meio de uma grade de propriedade, o "editor de coleção de string" gera um "construtor no tipo 'System.string' não encontrado" exceção em tempo de execução.

Não posso mudar os atributos do ExcludeFiles Propriedade porque eles serão substituídos na próxima vez que qualquer alteração de configuração for feita. Portanto, devo anexar/adicionar o editor/editorattribute no tempo de execução.

O que eu quero fazer é adicionar o StringCollectionEditor em tempo de execução, mostrado abaixo como atributo em tempo de design.

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

Soluções

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)))

Você só precisa adicionar esse atributo uma vez, como a inicialização do aplicativo.

Método #2

Mais flexível. Veja Nicolas Cadilhac Resposta abaixo em Adicionando editor / editorattribute em tempo de execução (dinamicamente) à propriedade de um objeto. Ele usa classes Derived CustomTypeDescriptor e TypeDescriptionProvider. Você só precisa adicionar o provedor uma vez, como a inicialização do aplicativo.

Foi útil?

Solução

Depois de dar minha primeira resposta, lembrei -me de outra solução dada por Marc Gravell que até comentei. Acredite ou não, você só precisa ligar para o typeDescriptor.addattributes ().

Isso está aqui: Como faço para injetar um UityPeeditor personalizado para todas as propriedades de um tipo de código fechado?.

Para o seu caso, ele dá:

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

Então, talvez você deva desmarcar minha resposta anterior e confirmar esta como a solução (embora todo o crédito vá para Marc). Mas minha postagem anterior ainda oferece uma boa técnica quando você precisa fazer coisas mais complexas com um typedescriptor.

Outras dicas

Você não pode. Um atributo só pode ser definido no horário de compilação (a menos que você gere o tipo dinamicamente, é claro)

Sim, é possível alterar dinamicamente um typedescriptor para que você retorne o uityPeeditor que deseja. Isso é explicado neste artigo. Mas observe que ele o adicionará para todas as propriedades desse tipo.

Peguei o código daqui e mudei aproximadamente para o seguinte:

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);
    }
}

Então você registra seu provedor:

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

Isso funciona bem, exceto que fará você descobrir que você tem outro problema: o MultilinestringEditor é um editor que funciona com o tipo de string, não com o tipo StringCollection. O que você realmente precisa é o StringCollectionEditor privado na estrutura .NET. Então, vamos substituir o 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) });
}

Eu espero que isso ajude.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top