我为PropertyGrid分配了以下类型的类:
public class Message{
[TypeConverter(typeof(UserConverter))]
public int SenderId { get; set; }
}
转换器
public class UserConverter: TypeConverter
{
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
{
return new StandardValuesCollection(_users);
}
}
当然是用户
public class User
{
public int Id { get; set; }
public string FullName { get; set; }
public override string ToString()
{
return User.fullName;
}
}
到目前为止一切正常(请注意:下图中的Sender
属性与上面SenderId
类中的Message
相同。此处的示例高度简化,以便于阅读) :
在我选择列表中的项目之前,我在mscorlib中得到一个例外:
System.ArgumentException occurred
_HResult=-2147024809
_message=Object of type 'System.String' cannot be converted to type 'System.Int32'.
HResult=-2147024809
IsTransient=false
Message=Object of type 'System.String' cannot be converted to type 'System.Int32'.
Source=mscorlib
StackTrace:
at System.ComponentModel.ReflectPropertyDescriptor.SetValue(Object component, Object value)
InnerException:
它似乎甚至没有通过我的TypeConverter
。我意识到属性类型是int并且我已经尝试覆盖ConvertTo
中的UserConverter
,但是当我在ComboBox
中选择一个项目时它似乎根本没有触及该方法。
如何控制这种组合框的返回值?在此特定情况下,我想返回Message.SenderId
而不是object.ToString()
覆盖。
答案 0 :(得分:0)
我已尝试在UserConverter中覆盖ConvertTo,但它似乎根本没有触及该方法
除了ConvertTo
之外,您还应该覆盖CanConvertFrom
和ConvertFrom
方法,以指定转换器实际上可以在所需类型之间进行转换。
无需覆盖CanConvertTo
,因为根据MSDN:
没有必要覆盖此方法以转换为字符串类型。Source
以下是基于您提供的模型的这些方法的简单实现:
public override bool CanConvertFrom(
ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public override object ConvertFrom(
ITypeDescriptorContext context, CultureInfo culture, object value)
{
return users.OfType<User>().First(u => u.ToString() == value.ToString()).Id;
}
public override object ConvertTo(
ITypeDescriptorContext context,
CultureInfo culture,
object value,
Type destinationType)
{
if (destinationType == typeof(string))
{
if (value is int)
{
return users.OfType<User>().First(u => u.Id == (int)value).ToString();
}
return value.ToString();
}
return base.ConvertTo(context, culture, value, destinationType);
}
注意:这是一个非常原始的实现,没有检查无效值,异常处理等。所以我不鼓励在生产中使用它。
答案 1 :(得分:0)
我想你现在已经找到了解决方案,但无论如何。 问题在于它正在尝试为用户找到int转换器... 如果将其添加到转换器的构造函数中(可能在静态构造函数中):
Attribute[] attr = new Attribute[1];
TypeConverterAttribute vConv = new TypeConverterAttribute(typeof(UserConverter));
attr[0] = vConv;
TypeDescriptor.AddAttributes(typeof(int), attr);
它会起作用,但它也会在你的课程中显示所有内容作为用户的下拉框;-)这根本不是你想要的。
如果我们可以像这样简单地为User类提供一个强制转换,那将会很酷:
public static implicit operator int(User user)
{
return user.Id; // implicit conversion
}
但不幸的是,这不起作用。它将继续尝试使用Int32并抛出异常。
实现此功能的唯一方法是为Id编写一个包装器:
public class SenderId
{
public int Id { get; set; }
public string DisplayMember {get; set;}
// this is how it will display the items:
public override string ToString()
{
return $"{DisplayMember} [{Id}]";
}
}
您还应该实现Equals和GetHashCode。然后像这样使用它:
public class Message
{
[TypeConverter(typeof(UserConverter))]
public SenderId SenderId { get; set; }
}
转换器:
public class UserConverter: TypeConverter
{
public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
{
return true;
}
public override StandardValuesCollection GetStandardValues(
ITypeDescriptorContext context)
{
return new StandardValuesCollection(_senderIds);
}
}
干杯。