- Create a custom property -- Enum DisplayNameAttribute
- Create a custom type converter for the property -- EnumDisplayNameConverter
- Decorate the enum values with the custom property
- Decorate the enum property with a type converter -- [TypeConverter(typeof(EnumDisplayNameConverter))]
I have done these and it does not work. It did work for me in V7, but I have been unable to make it work in V8 -- presumably my problem, not a V8 bug, but I need to understand it. I put breakpoints in all of the type converter functions and discovered that the type converter constructor is getting called for each appropriate enum, but no type converter methods are ever called, and hence the user-friendly name is never shown.
Custom property:
[AttributeUsage(AttributeTargets.Field)] public class EnumDisplayNameAttribute : DisplayNameAttribute { public EnumDisplayNameAttribute ( string s ) : base(s) { Name = s; } public string Name { get; private set; } }
class EnumDisplayNameConverter : EnumConverter { private Type _enumType; public EnumDisplayNameConverter(Type type) : base(type) { _enumType = type; } public override bool CanConvertTo(ITypeDescriptorContext context,Type destType) { return destType == typeof(string); } public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destType) { System.Reflection.FieldInfo field = _enumType.GetField(Enum.GetName(_enumType, value)); EnumDisplayNameAttribute attr = Attribute.GetCustomAttribute(field, typeof(EnumDisplayNameAttribute)) as EnumDisplayNameAttribute; return (attr != null) ? attr.Name : value.ToString(); // Could also return string.Empty in the null case } public override bool CanConvertFrom(ITypeDescriptorContext context,Type srcType) { return srcType == typeof(string); } public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) { foreach (System.Reflection.FieldInfo fi in _enumType.GetFields()) { EnumDisplayNameAttribute attr = Attribute.GetCustomAttribute(fi, typeof(EnumDisplayNameAttribute)) as EnumDisplayNameAttribute; if ((attr != null) && ((string)value == attr.Name)) return Enum.Parse(_enumType, fi.Name); } return Enum.Parse(_enumType, (string)value); } }
public enum SmoothType { [EnumDisplayName("Single EMA")] SingleEMA, [EnumDisplayName("Double EMA")] DoubleEMA, [EnumDisplayName("Triple EMA")] TripleEMA, [EnumDisplayName("No smoothing")] None }
private SmoothType valueSmoothType = SmoothType.None; [DefaultValue(SmoothType.None)] [RefreshProperties(RefreshProperties.All)] [TypeConverter(typeof(EnumDisplayNameConverter))] [Browsable(true)] [NinjaScriptProperty] // So the property can be used from NinjaScript (e.g. another indicator or a Strategy) [Display(Order = indicatorParameterBase + 0, Name = "Value line smoothing", GroupName = indicatorGridCategory, Description = "This property controls whether or not to apply smoothing to the indicator value plot")] public SmoothType ValueSmoothType { get { PrintGetEntry("returning " + valueSmoothType.ToString()); return valueSmoothType; } set { PrintSetEntry("old value=" + valueSmoothType.ToString() + " new value=" + value.ToString()); valueSmoothType = value; } }
Thanks,
EV
Comment