PropertyGridでEnum型の値を任意の文字列で表示する
新しく自分で宣言する型の場合はこれでかなり楽になります。
ですが、既存の型については各値に属性を付けることができない(できるのかもしれませんがわからなかった)ので、これは自前でTypeConverterを作るしかないかと思います。
それを最大限楽にできるように、元ネタのEnumDisplayNameConverterをさっくりと拡張してみました。
少しいじりつつ書いたので元コードとは部分的に書式が違います。
using System; using System.Collections.Generic; using System.Drawing; using System.Reflection; using System.Globalization; using System.ComponentModel; public class EnumDisplayNameConverter : EnumConverter { private Dictionary<object, string> table = new Dictionary<object, string>(); public EnumDisplayNameConverter(Type type) : base(type) { this.BuildTable(this.table); } protected virtual void BuildTable(System.Collections.Generic.Dictionary<object, string> table) { return; } public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { string str = value as string; if (str == null) { return base.ConvertFrom(context, culture, value); } Dictionary<object, string>.Enumerator enumerator = this.table.GetEnumerator(); while (enumerator.MoveNext()) { if (enumerator.Current.Value == str) { return enumerator.Current.Key; } } foreach (FieldInfo field in base.EnumType.GetFields()) { string name = this.GetDisplayName(field, culture); if (name == str) { return field.GetValue(null); } } return base.ConvertFrom(context, culture, value); } public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { if (destinationType != typeof(string)) { return base.ConvertTo(context, culture, value, destinationType); } string ret; if (this.table.TryGetValue(value, out ret)) { return ret; } string valueName = Enum.GetName(base.EnumType, value); if (valueName != null) { FieldInfo field = base.EnumType.GetField(valueName); string name = this.GetDisplayName(field, culture); if (name != null) { return name; } } return base.ConvertTo(context, culture, value, destinationType); } private string GetDisplayName(FieldInfo field, CultureInfo culture) { if (field == null) { return null; } Type type = typeof(EnumDisplayNameAttribute); Attribute attr = Attribute.GetCustomAttribute(field, type); EnumDisplayNameAttribute disp = attr as EnumDisplayNameAttribute; return (disp == null) ? null : disp.GetName(culture); } }
肝はBuildTable()です。このクラスを継承してBuildTableをオーバーライドし、変換用のテーブルを構築してあげるだけで後は勝手に変換します。
それに加えてConvertFromとConvertToに変換テーブルを使用して変換する処理が追加されています。
まず変換テーブルで変換を実行し、変換できなければEnumDisplayNameAttributeの値を使用するようになっています。
ということで試しにSystem.Drawing.ContentAlignmentのConverterを作成してみました。
using System; using System.Drawing; public class ContentAlignmentDisplayNameConverter : EnumDisplayNameConverter { public ContentAlignmentDisplayNameConverter(Type type) : base(type) { } protected override void BuildTable(System.Collections.Generic.Dictionary<object, string> table) { table.Add(ContentAlignment.TopLeft, "左上"); table.Add(ContentAlignment.TopCenter, "中央上"); table.Add(ContentAlignment.TopRight, "右上"); table.Add(ContentAlignment.MiddleLeft, "左中央"); table.Add(ContentAlignment.MiddleCenter, "中央"); table.Add(ContentAlignment.MiddleRight, "右中央"); table.Add(ContentAlignment.BottomLeft, "左下"); table.Add(ContentAlignment.BottomCenter, "中央下"); table.Add(ContentAlignment.BottomRight, "右下"); } }
これくらいのコード量に収まる+書式が固定化されれば大分楽になりそうです。