带有自定义 PropertyDescriptor 的 PropertyGrid [英] PropertyGrid with Custom PropertyDescriptor
问题描述
我一直在努力让自定义 PropertyDescriptor 以我想要的方式与 PropertyGrid 一起工作.
I've been struggling quite a bit to get custom PropertyDescriptors to work the way I want with a PropertyGrid.
前提:
- 我有一个名为Animal"的类,它包含属性
Age
、Type
、Location
和Name
>. - 我有另一个名为AnimalGroup"的类,其中包含存储动物的
List
.包含此列表的类成员称为Members
. - 在程序的 UI 中,
PropertyGrid
表单元素将列出分配给 PropertGrid 的SelectedObject
属性的 AnimalGroup 中的动物.
- I have a class called "Animal" which contains the properties
Age
,Type
,Location
, andName
. - I have another class called "AnimalGroup" which contains a
List<Animal>
where animals are stored. The class member that contains this list is calledMembers
. - In the UI of the program, a
PropertyGrid
form element will list off the Animals in the AnimalGroup that is assigned to the PropertGrid'sSelectedObject
property.
第三点我可以很容易地工作(见下图).
The third bullet I can get working quite easily (see image below).
AnimalGroup 类实现了 ICustomTypeDescriptor
接口,以在其 Members
类成员中实现 Animals 的列表功能.
The AnimalGroup class implements the ICustomTypeDescriptor
interface to achieve the listing functionality of the Animals in its Members
class member.
不幸的是,正如您在上图中所见,属性值只是从 Animal 的 ToString 方法返回的值.
Unfortunately, as you can see in the image above, the property value is simply the value returned from the Animal's ToString method.
我希望用户能够编辑 PropertyGrid 中每个 Animal 的成员(年龄、类型、位置和名称).我怎样才能做到这一点?我认为需要某种类型的自定义编辑器.然而,老实说,我不知道从哪里开始,因为谷歌搜索并没有出现太多.
I'd like to allow users the ability to edit the members of each Animal in the PropertyGrid (Age, Type, Location, and Name). How can I achieve this? I assume there will need to be a custom editor of some type. Honestly, however, I have no idea where to get started as Googling hasn't turned up much for this.
以下是我遵循的教程:
- Add (Remove) Items to (from) PropertyGrid at Runtime
- Using PropertyGrid with a dictionary object (this tutorial seems really old)
如果您需要,这是我的代码(使用 .NET 4.0):
And if you need it, here's my code (using .NET 4.0):
Animal.cs
public class Animal
{
private String _Name;
public String Name
{
get { return _Name; }
set { _Name = value; }
}
private String _Type;
public String Type
{
get { return _Type; }
set { _Type = value; }
}
private String _Age;
public String Age
{
get { return _Age; }
set { _Age = value; }
}
private String _Location;
public String Location
{
get { return _Location; }
set { _Location = value; }
}
public override string ToString()
{
return this.Name + " - " + this.Type;
}
}
AnimalGroup.cs
public class AnimalGroup : ICustomTypeDescriptor
{
public List<Animal> Members;
public AnimalGroup()
{
this.Members = new List<Animal>();
}
public AttributeCollection GetAttributes()
{
return TypeDescriptor.GetAttributes(this, true);
}
public string GetClassName()
{
return TypeDescriptor.GetClassName(this, true);
}
public string GetComponentName()
{
return TypeDescriptor.GetComponentName(this, true);
}
public TypeConverter GetConverter()
{
return TypeDescriptor.GetConverter(this, true);
}
public EventDescriptor GetDefaultEvent()
{
return TypeDescriptor.GetDefaultEvent(this, true);
}
public PropertyDescriptor GetDefaultProperty()
{
return null;
}
public object GetEditor(Type editorBaseType)
{
return TypeDescriptor.GetEditor(this, editorBaseType, true);
}
public EventDescriptorCollection GetEvents(Attribute[] attributes)
{
return TypeDescriptor.GetEvents(this, attributes, true);
}
public EventDescriptorCollection GetEvents()
{
return TypeDescriptor.GetEvents(this, true);
}
public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
PropertyDescriptor[] pds = new PropertyDescriptor[this.Members.Count];
int i = 0;
foreach (Animal a in this.Members)
{
pds[i] = new AnimalPropertyDescriptor(a, attributes);
i++;
}
return new PropertyDescriptorCollection(pds);
}
public PropertyDescriptorCollection GetProperties()
{
return this.GetProperties(new Attribute[0]);
}
public object GetPropertyOwner(PropertyDescriptor pd)
{
return this.Members;
}
}
AnimalPropertyDescriptor.cs
public class AnimalPropertyDescriptor : PropertyDescriptor
{
private Animal property;
public AnimalPropertyDescriptor(Animal target, Attribute[] attrs)
: base(target.Name, attrs)
{
this.property = target;
}
public override bool CanResetValue(object component)
{
return false;
}
public override Type ComponentType
{
get { return null; }
}
public override object GetValue(object component)
{
return property;
}
public override bool IsReadOnly
{
get { return false; }
}
public override Type PropertyType
{
get { return this.property.GetType(); }
}
public override void ResetValue(object component)
{
// Not relevant.
}
public override void SetValue(object component, object value)
{
this.property = (Animal)value;
}
public override bool ShouldSerializeValue(object component)
{
return false;
}
}
仅供参考,我知道代码有点荒谬(带有名称的动物、动物群体等).
FYI, I am aware that the code is a bit ridiculous (Animals with names, animal groups, etc).
推荐答案
您似乎缺少转换器:
internal class AnimalConverter : ExpandableObjectConverter {
public override object ConvertTo(ITypeDescriptorContext context,
CultureInfo culture,
object value,
Type destinationType) {
if (destinationType == typeof(string) && value is Animal) {
Animal a = (Animal)value;
return a.ToString();
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
然后装饰你的动物:
[TypeConverter(typeof(AnimalConverter))]
public class Animal {...}
发现这个代码项目 自定义显示PropertyGrid 中的集合数据很有帮助.
Found this Code Project Customized display of collection data in a PropertyGrid helpful.
这篇关于带有自定义 PropertyDescriptor 的 PropertyGrid的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!