【问题标题】:unwrapping nullable<T> to get T in IValueConverter展开 nullable<T> 以在 IValueConverter 中获取 T
【发布时间】:2018-07-10 21:09:19
【问题描述】:

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

我遇到的问题是 Convert 很简单,我返回一个字符串,但 ConvertBack 需要确切的类型(例如,返回 long 到 short 绑定只会失败,而不是截断)。话虽这么说,我们的数据源使用了所有 3 种数据类型(+nullable),我不想写 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;
}      

【问题讨论】:

  • 那么你的问题是什么?在您的代码中,我看到:“工作版本”。它已经工作了吗?
  • 这段代码不起作用吗?不清楚您需要什么帮助。
  • Nullable.GetUnderlyingType 已经在类型方面进行了展开。对于这些值,它只会在您取消装箱结果时自动工作。 object 从不 包含可为空的实例,但您始终可以将其内容拆箱为可为空的类型。
  • 刚发帖就知道了,是不是直接删问题最好?

标签: c# type-conversion ivalueconverter


【解决方案1】:

不久前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}}"/>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-15
    • 2017-04-01
    • 1970-01-01
    • 2016-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多