はじめに
EnumをBindingする際、ComboBoxで選択できるようにしたい。
ViewModelでEnumの値リストを持たせてあげればできるが、毎回それを用意するのは面倒なので、他に良い方法がないか調べてみた。
結果としては、ObjectDataProviderを使用するとEnumの列挙が可能である。
さらに、TypeConverter属性を使用することで、Description属性で与えた自由な説明で表示が可能であった。
単純にEnumを列挙する
Enumの定義
public enum SampleEnum
{
A,
B,
C
}
リソース定義
<ResourceDictionary>
<ObjectDataProvider x:key="Enums"
MethodName="GetValues"
ObjectType="{x:Type enums:SampleEnum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="enums:SampleEnum" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</ResourceDictionary>
ComboBox
<ComboBox ItemsSource="{Binding Source={StaticResource Enums}}"
SelectedItem="{Binding}" />
上記の場合、通常のEnumの値(今回の例だと「A」「B」「C」)がComboBoxの選択肢として表示される。
Description属性で指定した文字列を表示する
Description属性を用いて、内部と表示部分の表記を分けられるようにする。
EnumDescriptionConverter.cs
using System;
using System.ComponentModel;
namespace Sample
{
public class EnumDescriptionConverter : EnumConverter
{
public EnumDescriptionConverter(Type type) : base(type)
{
}
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
if (value != null)
{
var fi = value.GetType().GetField(value.ToString());
if (fi != null)
{
var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
return ((attributes.Length > 0) && (!string.IsNullOrEmpty(attributes[0].Description))) ? attributes[0].Description : value.ToString();
}
}
return string.Empty;
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
}
Enumの定義
[TypeConverter(typeof(EnumDescriptionConverter))]
public enum SampleEnum
{
[Description("選択肢1")]
A,
[Description("選択肢2")]
B,
[Description("選択肢3")]
C
}
上記によって、Description属性で指定した文字列(今回の例だと「選択肢1」「選択肢2」「選択肢3」)がComboBoxの選択肢として表示される。