Why
- 之前我发表过有关于在
WPF中如何在ComboBoc绑定枚举,主要是扩展一个标记语言,但是我在实际使用的时候发现这个方法还是有弊端,例如每一次都要指定类型然后指定key,这就显得有点扯淡了,所以我使用了另一种更加灵活的方法。
How
- 使用
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"库。
- 新建一个枚举
DeviceType
public enum DeviceType
{
[Description("默认")]
Default,
[Description("打印机")]
Printer,
[Description("扫描仪")]
Scanner,
[Description("网络打印机")]
Fax,
[Description("多功能一体机")]
MultiFunction
}
public class ComboxBehavior : Behavior<ComboBox>
{
public Type ItemType
{
get { return (Type)GetValue(ItemTypeProperty); }
set { SetValue(ItemTypeProperty, value); }
}
public static readonly DependencyProperty ItemTypeProperty =
DependencyProperty.Register("ItemType", typeof(Type), typeof(ComboxBehavior), new PropertyMetadata(null));
protected override void OnAttached()
{
AssociatedObject.Loaded += AssociatedObject_Loaded;
}
protected override void OnDetaching()
{
AssociatedObject.Loaded -= AssociatedObject_Loaded;
}
private void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
if (ItemType == null || !ItemType.IsEnum)
{
return;
}
foreach (var fieldInfo in ItemType.GetFields())
{
var description = fieldInfo.GetCustomAttribute<DescriptionAttribute>();
if (description == null)
{
continue;
}
AssociatedObject.Items.Add(description.Description);
}
}
}
- 新建一个
Enum2ObjConverter,因为控件里显示的是标签里的内容而不是枚举本身,所以需要有个转换。
public class Enum2ObjConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return null;
Type enumType = value.GetType();
if (!enumType.IsEnum)
return value;
foreach (var fieldInfo in enumType.GetFields())
{
var description = fieldInfo.GetCustomAttribute<DescriptionAttribute>();
if (description == null)
{
continue;
}
var a = fieldInfo.GetValue(null);
if (fieldInfo.GetValue(null).Equals(value))
{
return description.Description;
}
}
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return null;
if (!targetType.IsEnum)
return value;
object result = null;
foreach (var fieldInfo in targetType.GetFields())
{
var description = fieldInfo.GetCustomAttribute<DescriptionAttribute>();
if (description != null && description.Description == value.ToString())
{
result = fieldInfo.GetValue(null);
break;
}
}
return result;
}
}
- 具体使用方法(因为
Enum2ObjConverter就不写了)
<ComboBox Margin="5" SelectedItem="{Binding DeviceType, Mode=TwoWay, Converter={StaticResource Enum2ObjConverter}}">
<i:Interaction.Behaviors>
<b:ComboxBehavior ItemType="{x:Type comm:DeviceType}" />
</i:Interaction.Behaviors>
</ComboBox>
<TextBlock Margin="5" Text="{Binding DeviceType}" />
- 传入的时候需要传入一个类型,使得可以进行反射。
- 下面那个就会实时显示枚举值。
Tips