我的一个wpf程序需要把portable lib中的某一个类的属性用propertygrid展示出来
对于复杂的成员类型比如class或者struct,我上网搜索了下,需要用TypeConverter标记该属性是一个展开属性,如下
class B
{
A myA;
[TypeConverter(typeof(ExpandableObjectConverter))]
public A MyA
{
get{..}
set{..}
}
}但现在的问题是,我所引用的库是个portable lib,它能引用的references很有限,好像不包括这个TypeConverter.我是个新手,也仔细搜索了一通,但还是没找到什么好的办法。
求教,谢谢。
对于复杂的成员类型比如class或者struct,我上网搜索了下,需要用TypeConverter标记该属性是一个展开属性,如下
class B
{
A myA;
[TypeConverter(typeof(ExpandableObjectConverter))]
public A MyA
{
get{..}
set{..}
}
}但现在的问题是,我所引用的库是个portable lib,它能引用的references很有限,好像不包括这个TypeConverter.我是个新手,也仔细搜索了一通,但还是没找到什么好的办法。
求教,谢谢。
我看也有其他人问过关于展开的问题:http://topic.csdn.net/u/20100603/14/393795e6-1536-401f-91b6-9cc0c562311f.html
http://www.cnblogs.com/zhuqil/archive/2010/09/02/Wpf-PropertyGrid-Demo.html
{
private static TypeDescriptionProvider defaultTypeProvider =
TypeDescriptor.GetProvider(typeof(Object)); public ObjectDescriptionProvider() : base(defaultTypeProvider) { } public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
{
ICustomTypeDescriptor defaultDescriptor = base.GetTypeDescriptor(objectType, instance);
return objectType.IsPrimitive ? defaultDescriptor : new ObjectCustomTypeDescriptor(defaultDescriptor);
}
}
public class ObjectCustomTypeDescriptor : CustomTypeDescriptor
{
public ObjectCustomTypeDescriptor(ICustomTypeDescriptor parent)
: base(parent) { } public override AttributeCollection GetAttributes()
{
var attributes = base.GetAttributes().Cast<Attribute>().ToList();
if (!attributes.Exists(t => t is TypeConverterAttribute))
{
attributes.Add(new TypeConverterAttribute(typeof(ExpandableObjectConverter)));
}
return new AttributeCollection(attributes.ToArray());
}
}
请在程序的一开始运行一次如下代码(只需要一次)
ObjectDescriptionProvider provider = new ObjectDescriptionProvider();
TypeDescriptor.AddProvider(provider, typeof(Object));
如果你的类继承某个接口,那么这里的typeof(Object)可以改为你的接口类型。
我照着写了下,发现有变化,原来无法展开的属性出现了个展开箭头,但我点下去之后,还是无法展开,而且值无法修改。我详细说下我的情况:
我有两个portable lib,假设他们叫A和B。
A中有个processor类,他里面的属性类型是定义在B中的Level。
B中的Level只是简单的属性:
public byte byte1;
public double double1;
我在WPF中引用A的processor类,并希望把这个类的实例显示在propertygrid里面。我现在的问题是,我看前辈说,无法展开的属性取决于类型的toString重写,但我如果重写了Level类的ToString,是不是用户也无法通过property grid修改其值?我看前辈的代码,是不是类似于动态提供给Level类一个属性ExpandableObjectConverter?我需不需要继承ExpandableObjectConverter,自己写一个converter,实现ConvertTO, ConvertFrom一类的方法来解决这个问题?非常感谢
如果你还有疑问,我可以把我的测试代码放上: public class User
{
public int Id { get; set; }
public string Name { get; set; } public override string ToString()
{
return this.Id + "," + this.Name;
}
} public class Post
{
public int Id { get; set; }
public User Owner { get { return new User(); } }
public string Content { get; set; }
public Comment Comment { get { return new Comment(); } }
}
public class Comment
{
public int Id { get; set; }
public string CommentData { get; set; }
}
public Window1()
{
InitializeComponent(); ObjectDescriptionProvider provider = new ObjectDescriptionProvider();
TypeDescriptor.AddProvider(provider, typeof(Object));
PropertyGrid1.SelectedObject = new Post();
}
{
public Window1()
{
InitializeComponent(); ObjectDescriptionProvider provider = new ObjectDescriptionProvider();
TypeDescriptor.AddProvider(provider, typeof(Object));
PropertyGrid1.SelectedObject = new Post();
}
} public class ObjectDescriptionProvider : TypeDescriptionProvider
{
private static TypeDescriptionProvider defaultTypeProvider =
TypeDescriptor.GetProvider(typeof(Object)); public ObjectDescriptionProvider() : base(defaultTypeProvider) { } public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
{
ICustomTypeDescriptor defaultDescriptor = base.GetTypeDescriptor(objectType, instance);
return (objectType.IsPrimitive || objectType == typeof(string)) ? defaultDescriptor : new ObjectCustomTypeDescriptor(defaultDescriptor);
}
}
public class ObjectCustomTypeDescriptor : CustomTypeDescriptor
{
public ObjectCustomTypeDescriptor(ICustomTypeDescriptor parent)
: base(parent) { } public override AttributeCollection GetAttributes()
{
var attributes = base.GetAttributes().Cast<Attribute>().ToList();
if (!attributes.Exists(t => t is TypeConverterAttribute))
{
attributes.Add(new TypeConverterAttribute(typeof(ExpandableObjectConverter)));
}
return new AttributeCollection(attributes.ToArray());
}
} public class User
{
public int Id { get; set; }
public string Name { get; set; } public override string ToString()
{
return this.Id + "," + this.Name;
}
} public class Post
{
User owner = new User();
Comment comment = new Comment();
public int Id { get; set; }
public User Owner { get { return owner; } }
public string Content { get; set; }
public Comment Comment { get { return comment; } }
}
public class Comment
{
public int Id { get; set; }
public string CommentData { get; set; }
}
至于原理的确是动态给一个Object类型提供ExpandableObjectConverter,因为这个ExpandableObjectConverter功能有限,如果至少它没有实现ConvertFrom,因此不能在未展开的情况下编辑,除非自己继承并提供支持。
public Window1()
{
InitializeComponent(); ObjectDescriptionProvider provider = new ObjectDescriptionProvider();
TypeDescriptor.AddProvider(provider, typeof(Object));
PropertyGrid1.SelectedObject = new Post();
}这里typeof 不需要指明是user或者comment类吗?
TypeDescriptor.AddProvider(provider, typeof(Object));
另外给你一个小技巧,CSDN的论坛最近频繁抽风,不但经常404,还出现楼层掉落现象,比如我这里12楼就掉落了。
当你看到楼层不连续的时候,就需要在管理菜单里面反复“生成帖子”,否则看不全帖子的内容。给CSDN管理员的建议:如果CSDN一直这样下去,以后将不来这里了,去cnblog看看吧,人家的博问显示非常及时,从未有丢失内容或404的现象,功能强大带邮件提醒,做得非常人性化,相比之下,这里的论坛程序太垃圾了,而人气应该都是刷出来的。
不过我这里还是无法展开,只能出现一个展开的箭头,点完之后没反应。我打算试着自己写一个converter实现convertto, convertfrom什么的,试一下。
非常感谢,你提供的这种动态增加attr的办法很有用。
一般情况下,属性都是共有的,类的实例不为null的话,都是可以展开并显示的。
InLow:25, InHigh: 232, OutLow: 0, OutHigh: 10, Gamma: 1.18
虽然不如展开菜单方便,但也可以用了。我再按照你说的试下重载getproperties。
非常感谢你的帮助。