在 WPF 中将 Int 属性数据绑定到 Enum
Posted
技术标签:
【中文标题】在 WPF 中将 Int 属性数据绑定到 Enum【英文标题】:Data binding Int property to Enum in WPF 【发布时间】:2014-01-09 12:35:24 【问题描述】:下面是我拥有的一个类的简化示例:
public class ExampleClassDto
public int DriverTypeId
我还有一个 Enum,它将 DriverType 的 Id 映射到有意义的名称:
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 的属性成为不同的类型。还有其他更优雅的解决方案吗?
谢谢!
【问题讨论】:
DriverTypeId 不能是 DriverType 类型吗? 可以,但是 Dto 来自一个单独的库,我现在无法更改 =\ 那么为什么不扩展现有的类 (public partial class
) 并创建一个类型为 DriverType
的属性来获取/设置 DriverTypeId
呢?
@gleng:我认为,在这种情况下,我宁愿只保留转换器属性。我想知道是否还有其他方法可以在 XAML 中使用 SelectedValue 或 SelectedItem,或者 ValueConverter 是否可以发挥作用
我记得我做了一个通用的IntToEnum
转换器,我会大量使用它。 ConverterParameter
通常设置为 x:Type local:MyEnum
以将枚举类型传递给它,它会将绑定的 int 转换为该枚举值/从该枚举值转换。可能值得花点时间为您的公共图书馆制作一个。
【参考方案1】:
接受的答案要求您将枚举的类型指定为每个绑定的转换器参数。
如果您绑定到枚举属性,转换器可以从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 值之间翻转值的类型。源代码中没有硬编码的枚举类型,因此可重用。
【讨论】:
这似乎不适用于组合框,因为所选值是对象。接收 int 时的目标类型将是 object,因此您将不知道要转换为哪个枚举。 @aliceraunsbaek 你是对的,绑定目标必须提供枚举类型才能使这种方法工作。在像您这样的情况下,接受的答案可能会更好。 我已经通过添加一个可选的EnumType
属性来解决这个问题,该属性在设置后将取代targetType
。基本上,转换器可以在两种不同的模式下运行:静态,枚举类型被显式设置;或动态,由Convert
参数确定。【参考方案2】:
你可以有一个通用转换器说EnumConverter
,它将convert int to Enum
在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 的命名空间。
【讨论】:
太棒了。那效果很好。只需将以下内容添加到我的主资源字典中,我就可以使用 EnumConverter 作为资源:<converter:EnumConverter xmlns:converter="clr-namespace:Some.Name.Space.Helpers" x:Key="EnumConverter"/>
。非常高兴我可以在其他使用枚举的 ViewModel 中重用它。谢谢!【参考方案3】:
首先将枚举存储为 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;
【讨论】:
您能否提供更多信息,为什么这是一个坏主意? 见:原始痴迷以上是关于在 WPF 中将 Int 属性数据绑定到 Enum的主要内容,如果未能解决你的问题,请参考以下文章
如何将 Dictionary<enum, bool> 双向绑定到 WPF 中的 ListView 列?