Domanda

Come aggiungere l'EditorAttribute (Editor) per la proprietà di un oggetto a run-time?

Ho My.Settings.ExcludeFiles, che è stato creato dal designer impostazioni come Public Property ExcludedFiles() As Global.System.Collections.Specialized.StringCollection. Quando si modifica ExcludedFiles tramite una griglia di proprietà, la "Editor dell'insieme String" genera un "costruttore del tipo 'System.String' non trovato" run-time eccezioni.

Non riesco a modificare gli attributi della proprietà ExcludeFiles perché saranno sovrascritti la prossima volta che vengono apportate modifiche alle impostazioni. Pertanto, devo collegare / aggiungere l'Editor / EditorAttribute in fase di esecuzione.

Quello che voglio fare è aggiungere il StringCollectionEditor a run-time, come illustrato di seguito attributo in fase di progettazione.

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

Soluzioni

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

È sufficiente aggiungere questo attributo una volta, come ad esempio l'inizializzazione dell'applicazione.

Metodo # 2

Più flessibile. Vedi Nicolas Cadilhac rispondere a seguito Aggiunta Editor / EditorAttribute a runtime (dinamicamente) per un oggetto di proprietà . Esso utilizza classi derivate CustomTypeDescriptor e TypeDescriptionProvider. Basta aggiungere il provider una volta, come ad esempio l'inizializzazione dell'applicazione.

È stato utile?

Soluzione

Dopo aver dato la mia prima risposta, mi sono ricordato di un'altra soluzione data dal Marc Gravell che ho anche commentato. Che ci crediate o no, è sufficiente chiamare TypeDescriptor.AddAttributes ().

Questa è qui: Come faccio a iniettare un UITypeEditor personalizzato per tutte le proprietà di un tipo closed-source? .

Per il vostro caso si 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)))

Così forse si dovrebbe deselezionare la mia risposta precedente e confermare questa come la soluzione (anche se tutto il merito va a Marc). Ma il mio precedente post vi dà ancora una buona tecnica quando si ha bisogno di fare cose più complesse con un TypeDescriptor.

Altri suggerimenti

Non è possibile. Un attributo può essere definito solo in fase di compilazione (a meno che non si genera il tipo dinamico ovviamente)

Sì, è possibile cambiare dinamicamente un TypeDescriptor in modo che ritorni l'UITypeEditor che si desidera. Questo è spiegato in questo articolo . Ma si noti che questo verrà aggiunto per tutte le proprietà di questo tipo.

Ho afferrato il codice da qui e grosso modo cambiato per il seguente:

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

Poi si registra il fornitore:

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

Questo metodo funziona bene, tranne che vi farà scoprire di non avere un altro problema: MultilineStringEditor è un editor che funziona con il tipo String, non con il tipo StringCollection. Che cosa hai veramente bisogno è lo StringCollectionEditor privato nel quadro .Net. Quindi cerchiamo di sostituire GetEditor da:

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

Spero che questo aiuta.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top