2011-08-18 26 views
8

我想能够说是否可以创建一个通用的Int-to-Enum转换器?

<DataTrigger Binding="{Binding SomeIntValue}" 
      Value="{x:Static local:MyEnum.SomeValue}"> 

,并把它作为解决如果Trueint值等于(int)MyEnum.Value

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

有没有一种通用的方法来创建一个转换器,可以给我这种功能?

回答

4

我想我想通了

我只需要设置我ConverterParameter整数工作的完美解决方案而不是Value等于我要找的枚举,并评估真/假的

<DataTrigger Value="True" 
      Binding="{Binding SomeIntValue, 
       Converter={StaticResource IsIntEqualEnumConverter}, 
       ConverterParameter={x:Static local:MyEnum.SomeValue}}"> 

转换

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

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

这不,虽然,因为它不会与代表多个枚举的二进制值的ORing

+0

如何获得'Converter'中的枚举类型? – Rachel

3

你也可以去周围的其他方法和使用自定义标记扩展转换枚举为int的价值。

<DataTrigger Binding="{Binding Path=MyNumber}" 
      Value="{Markup:EnumToInt {x:Static Visibility.Visible}}"> 

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; 
    } 
} 
+0

我从来没有遇到过MarkupExtensions,谢谢!每天还在学习新的东西:) – Rachel

+0

同样在这里实际上,我刚开始使用他们,他们可以很方便:) –

1

我们要做到这一点,在过去几次一样,所以我们建立了一些扩展方法(上的int,long等等)来帮助我们。所有这些的核心是在单一的静态通用TryAsEnum方法实现:

/// <summary> 
    /// Helper method to try to convert a value to an enumeration value. 
    /// 
    /// If <paramref name="value"/> is not convertable to <typeparam name="TEnum"/>, an exception will be thrown 
    /// as documented by Convert.ChangeType. 
    /// </summary> 
    /// <param name="value">The value to convert to the enumeration type.</param> 
    /// <param name="outEnum">The enumeration type value.</param> 
    /// <returns>true if value was successfully converted; false otherwise.</returns> 
    /// <exception cref="InvalidOperationException">Thrown if <typeparamref name="TEnum"/> is not an enum type. (Because we can't specify a generic constraint that T is an Enum.)</exception> 
    public static bool TryAsEnum<TValue, TEnum>(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; 
    } 

此实现处理与[旗]属性定义与任何基本类型枚举,以及枚举。

6

可以在可重用的方式中在枚举值及其基础整型之间创建一个转换器 - 也就是说,您无需为每个枚举类型定义一个新的转换器。有足够的信息提供给ConvertConvertBack

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 /枚举值之间的值的类型。没有硬编码的枚举类型。

相关问题