以下是我所拥有的课程的简化示例:
public class ExampleClassDto
{
public int DriverTypeId
}
我还有一个Enum,它将DriverType的Ids映射到有意义的名称:
public enum DriverType
{
None,
Driver1,
Driver2,
Driver3
}
但是我想将这个在XAML中绑定到一个组合框。不幸的是,由于类型不匹配,它不喜欢这个。所以在我的ViewModel中,我必须创建第二个属性来映射两个
public class ExampleViewModel
{
private ExampleClassDto _selectedExampleClass;
public ExampleClassDto SelectedExampleClass
{
get { return _selectedExampleClass; }
set
{
_selectedExampleClass = value;
SelectedDriverType = (DriverType)_selectedExampleClass.DriverTypeId;
OnPropertyChanged("SelectedDeviceType");
}
}
public DriverType SelectedDriverType
{
get
{
if (_selectedDeviceType != null)
{
return (DriverType)_selectedDeviceType.DriverTypeId;
}
return DriverType.None;
}
set
{
_selectedDeviceType.DriverTypeId = (int) value;
OnPropertyChanged("SelectedDriverType");
}
}
}
然后我绑定到新属性。
<ComboBox ItemsSource="{Binding Source={StaticResource DriverTypeEnum}}" SelectedValue="{Binding SelectedDriverType, Mode=TwoWay}"/>
现在,这个工作,但感觉非常严重。它使用SelectedDriverType作为转换器。我想避免让DTO的属性变成另一种类型。还有其他更优雅的解决方案吗?
谢谢!
答案 0 :(得分:21)
您可以使用通用转换器EnumConverter
,convert int to Enum
将{1}}显示在XAML上,convert back from Enum to int
将在ViewModel类中显示。
它适用于任何枚举类型。您只需要在转换器参数中传递枚举类型。
public class EnumConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
Enum enumValue = default(Enum);
if (parameter is Type)
{
enumValue = (Enum)Enum.Parse((Type)parameter, value.ToString());
}
return enumValue;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
int returnValue = 0;
if (parameter is Type)
{
returnValue = (int)Enum.Parse((Type)parameter, value.ToString());
}
return returnValue;
}
}
XAML用法:
<ComboBox ItemsSource="{Binding Source={StaticResource DriverTypeEnum}}"
SelectedValue="{Binding DriverTypeId,
Converter={StaticResource EnumConverter},
ConverterParameter={x:Type local:DriverType}}"/>
local
是声明DriverType的命名空间。
答案 1 :(得分:6)
接受的答案要求您在每个绑定上指定枚举类型作为转换器参数。
如果绑定到枚举属性,转换器可以从targetType
属性确定枚举类型,这可能更符合人体工程学且不易出错。
public sealed class BidirectionalEnumAndNumberConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return null;
if (targetType.IsEnum)
{
// convert int to enum
return Enum.ToObject(targetType, value);
}
if (value.GetType().IsEnum)
{
// convert enum to int
return System.Convert.ChangeType(
value,
Enum.GetUnderlyingType(value.GetType()));
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
// perform the same conversion in both directions
return Convert(value, targetType, parameter, culture);
}
}
无论基础枚举类型如何int
,short
,byte
......),这也都有效。
调用时,此转换器仅基于value
和targetType
值在int / enum值之间翻转值的类型。源中没有硬编码的枚举类型,因此它非常可重用。
答案 2 :(得分:4)
首先将枚举存储为int是一个坏主意。无论如何,我会使用双向代理属性而不是单独的类:
public int DriverTypeId { get; set; }
public DriverType IntAsEnum // proxy property, doesn't store any value, only does the conversion
{
get { return (DriverType)DriverTypeId; }
set { DriverTypeId = (int)value; }
}