Quando si sviluppano componenti personalizzati, è sempre una buona idea quella di fornire un supporto a Design Time per l'utilizzatore; finché si ha a che fare con tipi comuni vengono già forniti editor standard (ad esempio, per il DateTime la Property Grid mostra sullo schermo una sorta di DateTimePicker), ma in altri casi è necessario costruire un custom editor derivando dalla classe UITypeEditor.
L'implementazione di un editor è realizzata sempre effettuando l'override di alcuni metodi particolari, dall'interno dei quali è sempre possibile ottenere una reference all'oggetto correntemente in editing tramite un ITypeDescriptorContext:
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
// qui recupero l'istanza dell'oggetto attualmente in modifica
Component objectInEdit = context.Instance;
// ... more code here ...
}
Cosa cambia in presenza di un Extender Provider
Un Extender Provider è un componente che, a design time, permette di aggiungere una nuova voce alla property grid di alcune tipologie di controlli; si pensi, ad esempio, a ciò che avviene inserendo in una form un controllo ToolTip (per approfondimenti, si rimanda alla MSDN Library). L'aspetto interessante è che questa implementazione è pressoché trasparente per il designer, che considera quella aggiunta una normalissima proprietà, che come tale può avere associato anche un Type Editor personalizzato. In questo scenario, però, lo snippet di codice precedente non è più valido nel caso in cui si voglia recuperare una reference all'extender, perché purtroppo context.Instance punta all'oggetto esteso e non a quello che estende. Per risolvere il problema, allora, è necessario procedere come segue:
public override object EditValue
(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
// recupero un attributo del tipo cercato dalla collection
ExtenderProvidedPropertyAttribute attr = (ExtenderProvidedPropertyAttribute)
context.PropertyDescriptor.Attributes[typeof(ExtenderProvidedPropertyAttribute)];
if (attr != null)
{
IExtenderProvider p = attr.Provider.Instance as IExtenderProvider;
// ... more code here ...
}
}
Il property descriptor della proprietà attualmente in modifica contiene una AttributeCollection a cui appartengono tutti gli attributi relativi al tipo della proprietà, più alcuni altri di ausilio al designer. Nel caso in cui essa sia generata da un Extender Provider, sarà presente anche un ExtenderProvidedPropertyAttribute. Esso, tra le altre, contiene la reference all'extender che si cercava, contenuta nella proprietà Provider.