你如何在PropertyGrid中使用NodaTime类?

时间:2012-11-30 19:33:19

标签: c# .net propertygrid nodatime

我正在转换一些应用程序代码以使用NodaTime类而不是System.DateTime。我的应用程序的一部分使用PropertyGrid控件允许用户编辑包含LocalDate和Instant的类。在不更改任何内容的情况下,PropertyGrid可以显示属性,但它们不再可编辑。允许用户编辑这些字段的最佳方法是什么。

为了说明,我们可以使用这个类作为我想要显示和编辑的事物类型的代表:

public class User
{
    public string Name { get; set; }
    public LocalDate BirthDate { get; set; }
    public Instant NextAppointment { get; set; }
}

1 个答案:

答案 0 :(得分:4)

迄今为止我最好的想法:

步骤1:创建TypeConverter,以便Noda类可编辑

public class ToAndFromStringTypeConverter : TypeConverter
{
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        if (sourceType == typeof(string))
            return true;
        else
            return base.CanConvertFrom(context, sourceType);
    }
    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        if (destinationType == typeof(string))
            return true;
        else
            return base.CanConvertTo(context, destinationType);
    }
}

public class LocalDateTypeConverter : ToAndFromStringTypeConverter
{
    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    {
        if (value is string)
        {
            DateTime parsed;
            if (!DateTime.TryParse((string)value, out parsed))
                throw new ArgumentException("Cannot convert '" + (string)value + "' to LocalDate.");
            else
                return new LocalDate(parsed.Year, parsed.Month, parsed.Day);
        }
        else
        {
            return base.ConvertFrom(context, culture, value);
        }
    }

    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(string))
        {
            var tvalue = (LocalDate)value;                
            try
            {
                var x = tvalue.ToString("yyyy-MM-dd");
                return x;
            }
            catch (NullReferenceException)
            {
                return "1900-1-1";
            }
            catch
            {
                throw new ArgumentException("Could not convert '" + value.ToString() + "' to LocalDate.");
            }                
        } 
        else 
            return base.ConvertTo(context, culture, value, destinationType);
    }

public class InstantTypeConverter : ToAndFromStringTypeConverter
{
    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    {
        if (value is string)
        {
            try
            {
                DateTime parsed = DateTime.Parse((string)value);
                LocalDateTime dt = LocalDateTime.FromDateTime(parsed);
                Instant i = dt.InZoneLeniently(DateTimeZoneProviders.Default.GetSystemDefault()).ToInstant();
                return i;
            }
            catch
            {
                throw new ArgumentException("Cannot convert '" + (string)value + "' to Instant.");
            }
        }
        else
        {
            return base.ConvertFrom(context, culture, value);
        }
    }

    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(string))
        {
            try
            {
                Instant tvalue = (Instant)value;
                LocalDateTime local = tvalue.InZone(DateTimeZoneProviders.Default.GetSystemDefault()).LocalDateTime;
                string output = LocalDateTimePattern.CreateWithInvariantCulture("yyyy-MM-dd HH:mm:ss.FFFFFF").Format(local);
                return output;
            }
            catch
            {
                throw new ArgumentException("Could not convert '" + value.ToString() + "' to LocalDate.");
            }                    
        }
        else
            return base.ConvertTo(context, culture, value, destinationType);
    }
}

第2步:注册TypeConverters

将此代码放在应用顶部:

TypeDescriptor.AddAttributes(typeof(LocalDate), new TypeConverterAttribute(typeof(LocalDateTypeConverter)));
TypeDescriptor.AddAttributes(typeof(Instant), new TypeConverterAttribute(typeof(InstantTypeConverter)));

步骤3:使用自定义集合编辑器处理List

之类的内容
public class NodaCollectionEditor : System.ComponentModel.Design.CollectionEditor
{
    public NodaCollectionEditor(Type collection_type) : base(collection_type) { }

    protected override object CreateInstance(Type itemType)
    {
        if (itemType == typeof(LocalDate))
            return LocalDateHelper.MinValue;
        else 
            return base.CreateInstance(itemType);
    }
}

可以通过将此属性添加到任何适当的属性来注册:

[System.ComponentModel.Editor(typeof(NodaCollectionEditor),typeof(System.Drawing.Design.UITypeEditor))]