2010-03-02 2 views
6

Я использую элемент управления PropertyGrid для редактирования некоторых объектов в своем приложении. Я использую пользовательские TypeConverters и TypeEditors для лучшего пользовательского интерфейса.Элемент сетки свойств и DoubleClick

У меня проблема с пользовательским TypeConverter для булевых свойств. Если у меня есть этот класс:

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

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

и создать экземпляр и установить его в качестве SelectedObject в PropertyGrid - все это хорошо до тех пор, пока пользователь не на сетке двойной клик свойство элемента формы собственности «Флаг». После DoubleClick возникает это сообщение: alt text http://tcks.wz.cz/property_grid_error.PNG

Класс TypeConverter выглядит:

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

+1

@ Николя Кадильяк, спасибо! Сколько часов я просто потратил на поиск этого ответа! – Ben

+0

Около 8, в моем случае>.>. Я унаследовал довольно сложный, типичный TypeConverter для преобразования общих перечислений, который имел эту проблему, и у меня было очень мало идей, с чего начать, учитывая, что обработка преобразования из PropertyGrid в основном является внутренней маской .net. Наконец нашел этот пост, и это было именно то, что я хотел, чтобы я нашел несколько часов назад. Благодаря! (В частности, он создавал карту [основного объекта -> строка], затем GetStandardValues ​​возвращал значения на карте, а не ключи. Yay.) – neminem

Смежные вопросы