In case anyone else is looking, here is what I ended up doing. I created a control extender, which alters the values of the drop down later in the lifecycle, if the enum values have a Display(Name = "xxx")
attribute. Then use this control extender as the form control for the required field.
public class EnumSelectorExtender : ControlExtender<CMSFormControls_System_EnumSelector>
{
private static readonly Dictionary<string, Dictionary<string, string>> DisplayNameLookup = new Dictionary<string, Dictionary<string, string>>();
private string _typeKey;
public override void OnInit()
{
Control.Load += ControlOnLoad;
}
private void ControlOnLoad(object sender, EventArgs e)
{
// Create a cached lookup table of the enum friendly names.
_typeKey = $"{Control.AssemblyName}.{Control.TypeName}";
EnsureDisplayNameLookup();
// Replace the values of the dropdown with friendly names if possible.
foreach (ListItem li in Control.CurrentSelector.Items)
{
if (DisplayNameLookup[_typeKey].TryGetValue(li.Text, out var displayName)) li.Text = displayName;
}
}
private void EnsureDisplayNameLookup()
{
if (!DisplayNameLookup.ContainsKey(_typeKey))
{
DisplayNameLookup.Add(_typeKey, new Dictionary<string, string>());
var type = TryGetEnumType(Control.AssemblyName, Control.TypeName);
if (type != null)
{
DisplayNameLookup[_typeKey] = type.GetFields(BindingFlags.Static | BindingFlags.Public)
.ToDictionary(f => $"{type.Name}.{f.Name}",
f => f.GetCustomAttribute<DisplayAttribute>()?.Name);
}
}
}
private Type TryGetEnumType(string assemblyname, string typeName)
{
if (!String.IsNullOrWhiteSpace(assemblyname) && !String.IsNullOrWhiteSpace(typeName))
{
var type = ClassHelper.GetClassType(assemblyname, typeName);
if ((type != null) && type.IsEnum)
{
return type;
}
}
return null;
}
}
This was after digging into the code for CMSFormControls_System_EnumSelector
to see how it works. It would be nice if that control took notice of the standard System.CompononentModel.Display
attribute out of the box.