Reputation: 792
C# allows the following functionality to display a user-friendly version of enums. The type converter takes the description attribute and uses it to generate a string. Can this be done in C++/CLI? From what I'm seeing, a 'public enum class' cannot have attributes on the enum members. This means I can't define the description attribute content for each enum. How can the friendly names be defined?
[TypeConverter(typeof(EnumDescriptionConverter))]
public enum MyEnum
{
[Description("Item1")]
Item1,
[Description("Item2")]
Item2,
}
class EnumDescriptionConverter : EnumConverter
{
private Type _enumType;
public EnumDescriptionConverter(Type type)
: base(type)
{
_enumType = type;
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destType)
{
return destType == typeof(string);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destType)
{
String ReturnString = "";
if (_enumType.GetCustomAttributes<FlagsAttribute>().Any())
{
foreach (var val in EnumExtensions.GetIndividualFlags((Enum)value))
{
FieldInfo fi = _enumType.GetField(Enum.GetName(_enumType, val));
DescriptionAttribute dna = (DescriptionAttribute)Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute));
if (ReturnString != "")
ReturnString += " | ";
if (dna != null)
ReturnString += dna.Description;
else
ReturnString += val.ToString();
}
}
else
{
FieldInfo fi = _enumType.GetField(Enum.GetName(_enumType, value));
DescriptionAttribute dna = (DescriptionAttribute)Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute));
if (ReturnString != "")
ReturnString += " | ";
if (dna != null)
ReturnString += dna.Description;
else
ReturnString += value.ToString();
}
return ReturnString;
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type srcType)
{
return srcType == typeof(string);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
foreach (FieldInfo fi in _enumType.GetFields())
{
DescriptionAttribute dna =
(DescriptionAttribute)Attribute.GetCustomAttribute(
fi, typeof(DescriptionAttribute));
if ((dna != null) && ((string)value == dna.Description))
return Enum.Parse(_enumType, fi.Name);
}
return Enum.Parse(_enumType, (string)value);
}
}
Upvotes: 2
Views: 2315
Reputation: 792
After researching this more, I resorted to the following type converter. It simply replaces an underscore in the enum member with a space. It can also handle flags.
ref class EnumDescriptionConverter : public System::ComponentModel::EnumConverter
{
private:
System::Type^ _enumType;
public:
EnumDescriptionConverter(System::Type^ type) : System::ComponentModel::EnumConverter(type)
{
_enumType = type;
}
bool CanConvertTo(System::ComponentModel::ITypeDescriptorContext^ context, System::Type^ destType)override
{
return destType == System::String::typeid;
}
System::Object^ ConvertTo(System::ComponentModel::ITypeDescriptorContext^ context, System::Globalization::CultureInfo^ culture, System::Object^ value, System::Type^ destType)override
{
return value->ToString()->Replace("_", " ");
}
bool CanConvertFrom(System::ComponentModel::ITypeDescriptorContext^ context, System::Type^ srcType)override
{
return srcType == System::String::typeid;
}
System::Object^ ConvertFrom(System::ComponentModel::ITypeDescriptorContext^ context, System::Globalization::CultureInfo^ culture, System::Object^ value)override
{
return System::Enum::Parse(_enumType, ((System::String^)value)->Replace(" ", "_")->Replace(",_", ", "));
}
};
Enums are defined like this:
[System::ComponentModel::TypeConverter(typeof(EnumDescriptionConverter))]
public enum class MyEnum
{
Item_1, // Appears as 'Item 1' when data bound or in a property grid
Item_2 // Appears as 'Item 2' when data bound or in a property grid
}
Upvotes: 0
Reputation: 283614
You've broken the cardinal rule of Stack Overflow questions: You didn't actually include real source code or the exact error message.
This code compiles just fine for me in Visual Studio 2013 in a brand new C++/CLI Console Application project:
using System::ComponentModel::DescriptionAttribute;
public enum class MyEnum
{
[Description("Item1")]
Item1,
[Description("Item2")]
Item2,
};
Upvotes: 0