2010-03-02 11 views
6

Używam kontrolki PropertyGrid do edycji niektórych obiektów w mojej aplikacji. Używam niestandardowych TypeConverters i TypeEditors dla lepszego interfejsu użytkownika.Element siatki właściwości i DoubleClick

Mam problem z niestandardowym TypeConverter dla właściwości boolowskiej. Jeśli mam tej klasy:

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

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

i utworzyć instancję i ustawić go jako SelectedObject w PropertyGrid - wszystko jest w porządku, dopóki użytkownik DoubleClicked na siatce właściwość postaci elementu „Flag” własności. Po DoubleClick jest podniesiona tę wiadomość: alt text http://tcks.wz.cz/property_grid_error.PNG

Klasa TypeConverter wygląda:

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; 
    } 
} 

Takie zachowanie jest bardzo mylące dla użytkowników. Jak mogę temu zapobiec? Metoda

Dzięki

Odpowiedz

8

Twoje GetStandardValues ​​() jest błędna. Musi zwrócić typ właściwości, a nie ciągi:

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

Dobrze, masz rację. Dzięki! – TcKs

+1

@Nicolas Cadilhac, Dzięki! Ile godzin spędziłem właśnie na szukaniu odpowiedzi! – Ben

+0

Około 8, w moim przypadku>.>. Odziedziczyłem dość skomplikowany, typowy TypeConverter do konwersji ogólnych wyliczeń, które miały ten problem, i nie miałem wielkiego pojęcia, od czego zacząć, biorąc pod uwagę, że obsługa konwersji z PropertyGrid jest głównie wewnętrzną magią .net. W końcu znalazłem ten post, który był dokładnie tym, czego chciałem znaleźć kilka godzin temu. Dzięki! (W szczególności był to tworzenie mapy [obiektu bazowego -> ciąg], a następnie GetStandardValues ​​zwracało wartości na mapie, a nie na klucze.) Yay.) – neminem

Powiązane problemy