是否可以创建一个通用的Int-to-Enum转换器?

我想能说

 

如果int值等于(int)MyEnum.Value其解析为True

我知道我可以创建一个返回(MyEnum)intValueConverter ,但是我必须为我在DataTriggers中使用的每个Enum类型创建一个转换器。

有没有一种通用的方法来创建一个能够给我这种​​function的转换器?

可以以可重用的方式在枚举值及其底层整数类型之间创建转换器 – 也就是说,您不需要为每个枚举类型定义新的转换器。 为ConvertConvert提供了足够的信息。

 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); } } 

调用时,此转换器仅基于valuetargetType值在int / enum值之间翻转值的类型。 没有硬编码的枚举类型。

我想我想通了

我只需要设置我的ConverterParameter而不是Value等于我正在寻找的Enum,并评估为True / False

  

变流器

 public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (parameter == null || value == null) return false; if (parameter.GetType().IsEnum && value is int) { return (int)parameter == (int)value; } return false; } 

你也可以反过来使用自定义标记扩展将枚举转换为int的int。

  

EnumToIntExtension

 public class EnumToIntExtension : MarkupExtension { public object EnumValue { get; set; } public EnumToIntExtension(object enumValue) { this.EnumValue = enumValue; } public override object ProvideValue(IServiceProvider provider) { if (EnumValue != null && EnumValue is Enum) { return System.Convert.ToInt32(EnumValue); } return -1; } } 

我们过去也想过几次这样做,所以我们构建了几个扩展方法(在int,long等)来帮助我们。 所有这些的核心都是在一个静态通用的TryAsEnum方法中实现的:

  ///  /// Helper method to try to convert a value to an enumeration value. /// /// If  is not convertable to , an exception will be thrown /// as documented by Convert.ChangeType. ///  /// The value to convert to the enumeration type. /// The enumeration type value. /// true if value was successfully converted; false otherwise. /// Thrown if  is not an enum type. (Because we can't specify a generic constraint that T is an Enum.) public static bool TryAsEnum( TValue value, out TEnum outEnum ) where TEnum : struct { var enumType = typeof( TEnum ); if ( !enumType.IsEnum ) { throw new InvalidOperationException( string.Format( "{0} is not an enum type.", enumType.Name ) ); } var valueAsUnderlyingType = Convert.ChangeType( value, Enum.GetUnderlyingType( enumType ) ); if ( Enum.IsDefined( enumType, valueAsUnderlyingType ) ) { outEnum = (TEnum) Enum.ToObject( enumType, valueAsUnderlyingType ); return true; } // IsDefined returns false if the value is multiple composed flags, so detect and handle that case if( enumType.GetCustomAttributes( typeof( FlagsAttribute ), inherit: true ).Any() ) { // Flags attribute set on the enum. Get the enum value. var enumValue = (TEnum)Enum.ToObject( enumType, valueAsUnderlyingType ); // If a value outside the actual enum range is set, then ToString will result in a numeric representation (rather than a string one). // So if a number CANNOT be parsed from the ToString result, we know that only defined values have been set. decimal parseResult; if( !decimal.TryParse( enumValue.ToString(), out parseResult ) ) { outEnum = enumValue; return true; } } outEnum = default( TEnum ); return false; } 

此实现处理具有任何基础类型的枚举,以及使用[Flags]属性定义的枚举。

您可以对int值执行ToString(),然后将其传递给静态Enum.Parse或Enum.TryParse方法,该方法采用您关心的枚举类型并返回适当的值。

这不是一个完美的解决方案,因为它不适用于表示多个枚举值的二进制ORing的整数