2011-08-18 16 views
8

Ben ancak o zaman,Genel Int-to-Enum Dönüştürücü oluşturmak mümkün mü?

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

söylemek ve int değer ben (MyEnum)intValue döndüren bir Converter yapabiliriz biliyorum (int)MyEnum.Value

eşitse o True olarak çözün edebilmek istiyorum DataTriggers'ımda kullandığım her Enum türü için bir dönüştürücü yapmalıyım.

Bana bu tür bir işlevsellik kazandıracak bir dönüştürücü oluşturmanın genel bir yolu var mı?

cevap

4

değerleri temsil tamsayılar ile çalışmaz, çünkü gerçi mükemmel bir çözüm değildir yerine aradığım Enum eşit ve true değerlendirmek/Yanlış Value arasında

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

Dönüştürücü

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 değerinde bir ToString() yapabilir ve sonra ilgilendiğiniz enum türünü alan ve uygun değeri döndüren statik Enum.Parse veya Enum.TryParse yöntemine iletebilirsiniz.

Bu ben sadece benim ConverterParameter ayarlamak için gerekli

bunu anladım düşünüyorum çoklu enum ikili ORing

+0

Enum Type'u "Dönüştürücü" içine nasıl alabilirim? – Rachel

3

Ayrıca başka bir yoldan gidebilir ve Enum'u özel bir İşaretleme Uzantısı kullanarak Değer'e int dönüştürebilirsiniz.

Örnek

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

EnumToIntExtension

Bu geçmişte de birkaç kez yapmak istediği, bu yüzden int üzerinde (birkaç uzatma yöntemleri inşa ettik
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 ile daha önce hiç karşılaşmadım, teşekkürler! Hala her gün yeni bir şeyler öğrenmek :) – Rachel

+0

Burada da aynı şeyi kullanmaya başladım ve çok kullanışlı olabilirler :) –

1

, uzun, vb) bize yardımcı olmak için. Tüm bu çekirdek tek bir statik genel TryAsEnum yöntem uygulanır:

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

Bu uygulama [Bayraklar] niteliğiyle tanımlanan altta yatan herhangi bir türü ile numaralamalar yanı sıra Çeteleler yönetir.

6

Enum değerleri ile bunların altında yatan integral türleri arasında yeniden kullanılabilir bir şekilde bir dönüştürücü oluşturmak mümkündür; yani, her bir enum türü için yeni bir dönüştürücü tanımlamanıza gerek yoktur. Bunun için Convert ve ConvertBack'a sağlanan yeterli bilgi var.

çağrılan
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); 
    } 
} 

, bu dönüştürücü value ve targetType değerlerine tamamen göre int/enum değeri arasındaki değerin türü çevirir. Sabit kodlanmış enum türleri yoktur.

İlgili konular