Hay varias maneras diferentes de hacerlo. Lo más simple es hacer algo similar a cómo ciertos productos i18n lo hacen: subclasificar el atributo e interceptar el texto; pero esto solo funciona si posee el tipo, y desde un atributo no puede acceder al contexto.
Los siguientes cosas para mirar serían TypeConverter
, ya que esto facilita el acceso a la vista de componentes-modelo sobre las propiedades, y es más simple que los siguientes dos opciones ;-P Esto funciona con PropertyGrid
, pero no DataGridView
etc.
Siguiente en la lista es ICustomTypeDescriptor
- no es una interfaz divertida de implementar, pero puede cambiar su propio descriptor de propiedad. Esto requiere que sea el propietario del tipo (para proporcionar el soporte de interfaz).
Por último, CustomTypeDescriptor
es como el pasado, pero funciona incluso para tipos que no posee, y permite el acceso a los metadatos ajustado, tanto en el tipo y nivel de objetos (todo lo demás sólo es compatible con objeto ).
¿Qué elegir? Sospecho que TypeConverter
sería el más sensato; necesita el contexto del objeto (que no proporciona un atributo subclasificado), pero no necesita la complejidad adicional.
Aquí hay un ejemplo; tenga en cuenta que en el código TypeConverter
tenemos acceso al contexto del objeto. Si el nombre es simple, ponerlo en el TypeConverter
(al crear la propiedad) debería ser suficiente.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
class MyFunkyTypeConverter : ExpandableObjectConverter
{
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
PropertyDescriptorCollection props = base.GetProperties(context, value, attributes);
List<PropertyDescriptor> list = new List<PropertyDescriptor>(props.Count);
foreach (PropertyDescriptor prop in props)
{
switch (prop.Name)
{
case "Distance":
list.Add(new DisplayNamePropertyDescriptor(
prop, "your magic code here"));
break;
default:
list.Add(prop);
break;
}
}
return new PropertyDescriptorCollection(list.ToArray(), true);
}
}
class DisplayNamePropertyDescriptor : PropertyDescriptor
{
private readonly string displayName;
private readonly PropertyDescriptor parent;
public DisplayNamePropertyDescriptor(
PropertyDescriptor parent, string displayName) : base(parent)
{
this.displayName = displayName;
this.parent = parent;
}
public override string DisplayName
{get { return displayName; } }
public override bool ShouldSerializeValue(object component)
{ return parent.ShouldSerializeValue(component); }
public override void SetValue(object component, object value) {
parent.SetValue(component, value);
}
public override object GetValue(object component)
{
return parent.GetValue(component);
}
public override void ResetValue(object component)
{
parent.ResetValue(component);
}
public override bool CanResetValue(object component)
{
return parent.CanResetValue(component);
}
public override bool IsReadOnly
{
get { return parent.IsReadOnly; }
}
public override void AddValueChanged(object component, EventHandler handler)
{
parent.AddValueChanged(component, handler);
}
public override void RemoveValueChanged(object component, EventHandler handler)
{
parent.RemoveValueChanged(component, handler);
}
public override bool SupportsChangeEvents
{
get { return parent.SupportsChangeEvents; }
}
public override Type PropertyType
{
get { return parent.PropertyType; }
}
public override TypeConverter Converter
{
get { return parent.Converter; }
}
public override Type ComponentType
{
get { return parent.ComponentType; }
}
public override string Description
{
get { return parent.Description; }
}
public override PropertyDescriptorCollection GetChildProperties(object instance, Attribute[] filter)
{
return parent.GetChildProperties(instance, filter);
}
public override string Name
{
get { return parent.Name; }
}
}
[TypeConverter(typeof(MyFunkyTypeConverter))]
class MyFunkyType
{
public double Distance {get;set;}
public double AnotherProperty { get; set; }
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new Form { Controls = {
new PropertyGrid { Dock = DockStyle.Fill,
SelectedObject = new MyFunkyType {
Distance = 123.45
}}
}});
}
}
Siempre puede configurarlo en 'Distancia' e incluir las unidades en el valor, p. "Distancia | 34 metros" y "Distancia | 112 pies". –
¿Cómo haré eso si mi tipo es un doble por ejemplo? – DogDog