数据绑定 Int 属性到 WPF 中的 Enum
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20707160/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Data binding Int property to Enum in WPF
提问by Killnine
Below is a simplified example of a class I have:
下面是我所拥有的一个类的简化示例:
public class ExampleClassDto
{
public int DriverTypeId
}
I also have an Enum that maps the Ids of DriverType to meaningful names:
我还有一个 Enum 将 DriverType 的 Id 映射到有意义的名称:
public enum DriverType
{
None,
Driver1,
Driver2,
Driver3
}
But I want to bind this in XAML to a combobox. Unfortunately, because of the type mismatch, it doesn't like this. So in my ViewModel, I have to create a second property to map the two
但我想将 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");
}
}
}
Then I bind to the new property.
然后我绑定到新属性。
<ComboBox ItemsSource="{Binding Source={StaticResource DriverTypeEnum}}" SelectedValue="{Binding SelectedDriverType, Mode=TwoWay}"/>
Now, this WORKS, but feels very gross. It's using SelectedDriverType as a converter. I want to avoid having to make the DTO's property a different type. Are there other, more elegant, solutions?
现在,这有效,但感觉很恶心。它使用 SelectedDriverType 作为转换器。我想避免必须使 DTO 的属性成为不同的类型。还有其他更优雅的解决方案吗?
Thanks!
谢谢!
回答by Rohit Vats
You can have a generic converter say EnumConverterwhich will convert int to Enumto show it on XAML and convert back from Enum to intto set back in your ViewModel class.
你可以有一个通用的转换器的发言权EnumConverter,这将convert int to Enum显示它在XAML并convert back from Enum to int在您的视图模型类集合回来。
It will work for any enum type. You just need to pass on type of enum in converter parameter.
它适用于任何枚举类型。您只需要在转换器参数中传递枚举类型。
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 usage :
XAML 用法:
<ComboBox ItemsSource="{Binding Source={StaticResource DriverTypeEnum}}"
SelectedValue="{Binding DriverTypeId,
Converter={StaticResource EnumConverter},
ConverterParameter={x:Type local:DriverType}}"/>
localis namespace where your DriverType is declared.
local是声明 DriverType 的命名空间。
回答by Drew Noakes
The accepted answer requires you to specify the enum's type as a converter parameter on each binding.
接受的答案要求您将枚举的类型指定为每个绑定的转换器参数。
If you are binding to an enum property, the converter can determine the enum type from the targetTypeproperty, which can be more ergonomic and less error prone.
如果您绑定到枚举属性,转换器可以根据属性确定枚举类型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);
}
}
This also works regardless of the underlying enum type (int, short, byte...).
这也适用于底层枚举类型 ( int, short, byte...)。
When invoked, this converter flips the value's type between int/enum value based purely on the valueand targetTypevalues. There are no hard-coded enum types in the source, so it's quite reusable.
调用时,此转换器纯粹基于value和targetType值在 int/enum 值之间翻转值的类型。源代码中没有硬编码的枚举类型,因此它非常可重用。
回答by fejesjoco
Storing an enum as an int is a bad idea in the first place. Anyway I would use a two-way proxy property instead of a separate class:
首先将枚举存储为 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; }
}

