コンボボックスに値を登録するために列挙型を使用しています。選択した列挙値の「説明」を表示するコンバーターを書きたいと思います。また、選択すると、列挙値が返されます。
オンラインのほとんどのコンバーターは、ConvertBack() メソッドを実装していません (これが、私がここに投稿している理由です)。
コンボボックスに値を登録するために列挙型を使用しています。選択した列挙値の「説明」を表示するコンバーターを書きたいと思います。また、選択すると、列挙値が返されます。
オンラインのほとんどのコンバーターは、ConvertBack() メソッドを実装していません (これが、私がここに投稿している理由です)。
[ValueConversion(typeof(MyEnum), typeof(String))]
public class MyEnumConverter : IValueConverter
{
public object Convert(object value,
Type targetType,
object parameter,
CultureInfo culture)
{
var enumVal = (MyEnum)value;
// in this example, this is an extension method
return enumValue.Description();
}
public object ConvertBack(object value,
Type targetType,
object parameter,
CultureInfo culture)
{
var enumDesc = value as string;
MyEnum val;
if (Enum.TryParse(typeof(MyEnum), strValue, out val))
{
return val;
}
return DependencyProperty.UnsetValue;
}
}
この例の拡張メソッドは次のようになります。
public static string Description(this MyEnum enumVal)
{
// you could use a switch statement here;
// or maybe a Dictionary
}
上記の例を補足して、列挙型を属性で装飾する方法を示します。
sealed class DescriptionAttribute : Attribute
{
readonly string description;
public DescriptionAttribute(string description)
{
this.description = description;
}
public string Description
{
get { return description; }
}
}
enum Vehicle
{
[Description("Benz")]
Car,
[Description("Volvo")]
Bus,
[Description("Honda")]
Bike
}
ところで、なぜ説明を列挙型に戻す必要があるのだろうか。列挙型自体を ItemSource として提供する場合、記述手法を使用して ComboBox に表示値を表示できますが、アイテムが選択されると、選択したアイテムとして列挙型を直接持つことができます。
これが私のうまくいく例です:
列挙定義:
public enum MyEnum
{
[Description("Exchange 2007")]
E2007,
[Description("Exchange 2010")]
E2010,
[Description("Exchange 2013")]
E2013,
};
ヘルパー クラス:
public static class cHelperClass
{
#region GetValuesAndDescriptions
public static object[] GetValuesAndDescriptions(Type enumType)
{
var kvPairList = new List<KeyValuePair<string, string>>();
var listValue = Enum.GetValues(enumType);
for (var i = 0; i < listValue.Length; i++)
{
var value = listValue.GetValue(i);
var enumValue = (Enum)listValue.GetValue(i);
kvPairList.Add(new KeyValuePair<string, string>(value.ToString(), GetDescription(enumValue)));
}
var valuesAndDescriptions = from kv in kvPairList select new
{
Value = kv.Key,
Description = kv.Value
};
return valuesAndDescriptions.ToArray();
}
public static string GetDescription(this Enum value)
{
var fieldInfo = value.GetType().GetField(value.ToString());
var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
return (attributes.Length > 0) ? attributes[0].Description : value.ToString();
}
public static string GetStringValue(this Enum enumItem)
{
return enumItem
.GetType()
.GetField(enumItem.ToString())
.GetCustomAttributes<StringValueAttribute>()
.Select(a => a.Value)
.FirstOrDefault() ?? enumItem.ToString();
}
public static string GetName(Type enumType, object value)
{
return Enum.GetName(enumType, value);
}
#endregion
}
XAML:
<UserControl.Resources>
<!-- ObjectDataProvider für WindowStyles -->
<ObjectDataProvider x:Key="myEnumResource" MethodName="GetValuesAndDescriptions" ObjectType="classes:cHelperClass">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="classes:MyEnum" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</UserControl.Resources>
<ComboBox ItemsSource="{Binding Source={StaticResource myEnumResource}}" DisplayMemberPath="Description" SelectedValuePath="Value" SelectedValue="{Binding MyEnum, Mode=TwoWay}" />