解开nullable <t>以获得IValueConverter中的T

时间:2018-07-10 12:11:21

标签: c# type-conversion ivalueconverter

我目前正在编写一个转换器,该转换器应将字​​符串解析为long / int / short并将值存储在绑定变量中。

我遇到的问题是Convert很容易,我返回了一个字符串,但是ConvertBack需要确切的类型(例如,将long返回为short绑定只会失败,而不是被截断)。话虽这么说,我们的数据源使用所有3种数据类型(可为空),并且我不想编写转换器的3个副本并正确使用它们,我希望有一个更智能的转换器。现在,我的代码如下所示(剩余的部分是TODO):

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
  var stringValue = value as string;
  var parsed = long.TryParse(stringValue, out long longValue);
  if (ValueTypeHelper.IsNullableType(targetType))
  {
    if (!parsed) return null;
    // TODO: this should unwrap the nullable Nullable<int> -> int
    //targetType = targetType.MemberType.GetType();
    // EDIT: The working version is below:
    targetType = Nullable.GetUnderlyingType(targetType);
  }

  if (!parsed) return 0;
  if (targetType.Equals(typeof(short))) return (short)longValue;
  if (targetType.Equals(typeof(int))) return (int)longValue;
  return longValue;
}      

1 个答案:

答案 0 :(得分:0)

前一段时间I found this converter,此后一直在与您类似的情况下使用它:

public class UniversalValueConverter : MarkupExtension, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        // obtain the conveter for the target type
        TypeConverter converter = TypeDescriptor.GetConverter(targetType);

        try
        {
            // determine if the supplied value is of a suitable type
            if (converter.CanConvertFrom(value.GetType()))
            {
                // return the converted value
                return converter.ConvertFrom(value);
            }
            else
            {
                // try to convert from the string representation
                return converter.ConvertFrom(value.ToString());
            }
        }
        catch (Exception)
        {
            return GetDefault(targetType);
            // return DependencyProperty.UnsetValue;
            // return null;
        }

    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        TypeConverter converter = TypeDescriptor.GetConverter(targetType);
        try
        {
            // determine if the supplied value is of a suitable type
            if (converter.CanConvertFrom(value.GetType()))
            {
                // return the converted value
                return converter.ConvertFrom(value);
            }
            else
            {
                // try to convert from the string representation
                return converter.ConvertFrom(value.ToString());
            }
        }
        catch (Exception)
        {
            return GetDefault(targetType);
            // return DependencyProperty.UnsetValue;
            // return null;
        }
    }

    private static UniversalValueConverter _converter = null;

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (_converter == null) _converter = new UniversalValueConverter();
        return _converter;
    }

    public UniversalValueConverter()
        : base()
    {
    }

    public static object GetDefault(Type type)
    {
        if (type.IsValueType)
        {
            return Activator.CreateInstance(type);
        }
        return null;
    }
}

要在xaml中使用:

xmlns:converters="clr-namespace:MyConvertersNamespace"

....

<TextBox="{Binding Path=MyProperty, Converter={converters:UniversalValueConverter}}"/>