2011-08-18 31 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 /枚舉值之間的值的類型。沒有硬編碼的枚舉類型。

相關問題