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
Dobrze, masz rację. Dzięki! – TcKs
@Nicolas Cadilhac, Dzięki! Ile godzin spędziłem właśnie na szukaniu odpowiedzi! – Ben
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