2010-03-02 40 views
6

我正在使用PropertyGrid控件编辑我的应用程序中的某些对象。我正在使用自定义的TypeConverters和TypeEditor以获得更好的用户界面。属性网格项目和DoubleClick

我有自定义TypeConverter布尔属性的问题。如果我有这个类:

public class MyClass { 
    public string Name { get; set; } 

    [System.ComponentModel.TypeConverter(typeof(BoolTypeConverter))] 
    public bool Flag { get; set; } 
} 

,我创建实例,并将其设置为SelectedObject在PropertyGrid中 - 一切都很好,直到用户属性网格项目形式“旗”财产上DoubleClicked。 DoubleClick会在提出了这个消息后:alt text http://tcks.wz.cz/property_grid_error.PNG

的类型转换器类如下:

public class BoolTypeConverter : System.ComponentModel.TypeConverter { 
    public const string TEXT_TRUE = "On"; 
    public const string TEXT_FALSE = "Off"; 
    public const string TEXT_NONE = "<none>"; 

    public override object CreateInstance(System.ComponentModel.ITypeDescriptorContext context, System.Collections.IDictionary propertyValues) { 
     object ret = base.CreateInstance(context, propertyValues); 
     return ret; 
    } 
    public override bool GetCreateInstanceSupported(System.ComponentModel.ITypeDescriptorContext context) { 
     bool ret = base.GetCreateInstanceSupported(context); 
     return ret; 
    } 
    public override bool IsValid(System.ComponentModel.ITypeDescriptorContext context, object value) { 
     bool ret; 
     if (value is string) { 
      string tmpValue = value.ToString().Trim(); 

      if (string.Compare(tmpValue, TEXT_NONE, StringComparison.InvariantCultureIgnoreCase) == 0) { 
       ret = true; 
      } 
      else if (string.Compare(tmpValue, TEXT_TRUE, StringComparison.InvariantCultureIgnoreCase) == 0) { 
       ret = true; 
      } 
      else if (string.Compare(tmpValue, TEXT_FALSE, StringComparison.InvariantCultureIgnoreCase) == 0) { 
       ret = true; 
      } 
      else { 
       bool blValue; 
       ret = bool.TryParse(tmpValue, out blValue); 
      } 
     } 
     else { 
      ret = base.IsValid(context, value); 
     } 

     return ret; 
    } 

    public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, Type sourceType) { 
     bool ret = false; 
     if (sourceType == typeof(string)) { 
      ret = true; 
     } 
     else { 
      ret = base.CanConvertFrom(context, sourceType); 
     } 

     return ret; 
    } 
    public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) { 
     object ret = null; 

     bool converted = false; 
     if (value is string) { 
      string tmpValue = value.ToString().Trim(); 
      if (string.Compare(tmpValue, TEXT_NONE, StringComparison.InvariantCultureIgnoreCase) == 0 
       || string.IsNullOrEmpty(tmpValue)) { 
       ret = null; 
       converted = true; 
      } 
      else if (string.Compare(tmpValue, TEXT_TRUE, StringComparison.InvariantCultureIgnoreCase) == 0) { 
       ret = true; 
       converted = true; 
      } 
      else if (string.Compare(tmpValue, TEXT_FALSE, StringComparison.InvariantCultureIgnoreCase) == 0) { 
       ret = false; 
       converted = true; 
      } 
      else { 
       bool blValue; 
       if (converted = bool.TryParse(tmpValue, out blValue)) { 
        ret = blValue; 
       } 
      } 
     } 

     if (false == converted) { 
      ret = base.ConvertFrom(context, culture, value); 
     } 
     return ret; 
    } 

    public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, Type destinationType) { 
     bool ret = false; 
     if (destinationType == typeof(bool)) { 
      ret = true; 
     } 
     else { 
      ret = base.CanConvertTo(context, destinationType); 
     } 

     return ret; 
    } 
    public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType) { 
     object ret = null; 

     bool converted = false; 
     if (destinationType == typeof(string)) { 
      if (null == value) { 
       ret = TEXT_NONE; 
       converted = true; 
      } 
      else if (value is bool? || value is bool) { 
       if ((bool)value) { ret = TEXT_TRUE; } 
       else { ret = TEXT_FALSE; } 

       converted = true; 
      } 
      else if (value is string) { 
       ret = value; 
       converted = true; 
      } 
     } 
     if (false == converted) { 
      ret = base.ConvertTo(context, culture, value, destinationType); 
     } 
     return ret; 
    } 

    public override StandardValuesCollection GetStandardValues(System.ComponentModel.ITypeDescriptorContext context) { 
     StandardValuesCollection ret; 
     Type tpProperty = context.PropertyDescriptor.PropertyType; 
     if (tpProperty == typeof(bool)) { 
      ret = new StandardValuesCollection(new string[]{ 
      TEXT_TRUE, TEXT_FALSE 
     }); 
     } 
     else if (tpProperty == typeof(bool?)) { 
      ret = new StandardValuesCollection(new string[]{ 
       TEXT_TRUE, TEXT_FALSE, TEXT_NONE 
      }); 
     } 
     else { 
      ret = new StandardValuesCollection(new string[0]); 
     } 

     return ret; 
    } 
    public override bool GetStandardValuesSupported(System.ComponentModel.ITypeDescriptorContext context) { 
     bool ret; 
     Type tpProperty = context.PropertyDescriptor.PropertyType; 
     if (tpProperty == typeof(bool) || tpProperty == typeof(bool?)) { 
      ret = true; 
     } 
     else { 
      ret = false; 
     } 

     return ret; 
    } 
} 

这种行为对于用户来说非常混乱。我怎样才能防止它?

谢谢

回答

8

您的GetStandardValues()方法是错误的。它必须返回属性类型,而不是字符串:

public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) 
{ 
    StandardValuesCollection ret; 
    Type tpProperty = context.PropertyDescriptor.PropertyType; 

    if (tpProperty == typeof(bool)) 
     ret = new StandardValuesCollection(new object[] { true, false }); 
    else if (tpProperty == typeof(bool?)) 
     ret = new StandardValuesCollection(new object[] { true, false, null }); 
    else 
     ret = new StandardValuesCollection(new object[0]); 

    return ret; 
} 
+0

太好了,您是对的。谢谢! – TcKs 2010-03-02 13:31:19

+1

@Nicolas Cadilhac,谢谢!我花了多少小时来寻找这个答案! – Ben 2012-03-29 19:39:18

+0

约8,在我的情况>。>。我继承了一个相当复杂的泛型TypeConverter,用于转换泛型枚举,而这个泛型枚举出现了这个问题,而且我几乎不知道从哪里开始,因为从PropertyGrid转换的处理大部分是内部的.net魔术。终于找到了这篇文章,这正是我几个小时前发现的。谢谢! (具体来说,它是创建[底层对象 - >字符串]的地图,然后GetStandardValues返回的是地图中的值而不是关键字。Yay。) – neminem 2012-04-17 16:15:52