netPropertyGrid动态生成属性页.docx
- 文档编号:6710250
- 上传时间:2023-01-09
- 格式:DOCX
- 页数:17
- 大小:100.27KB
netPropertyGrid动态生成属性页.docx
《netPropertyGrid动态生成属性页.docx》由会员分享,可在线阅读,更多相关《netPropertyGrid动态生成属性页.docx(17页珍藏版)》请在冰豆网上搜索。
netPropertyGrid动态生成属性页
对于这几个月的这个项目,一直想做个总结,但是鉴于本人记性之差,总是将这件事想起又忘记,终于在这个月工作的最后几天有了几天的空闲,把这个经验好好的记录下来。
PropertyGrid,.net框架下的一个控件,这是一个软件升级的项目,原来的软件用的是C++,控件用的还是第三方,这次升级到visualstudio.net4.0版本,原以为.net的东西用起来不会费劲的,没想到想要实现项目需要的效果还真没那么简单。
由于需要,我这里主要是为了能动态的生成属性页,还要带能动态生成下来菜单,所以今天主要从这方面总结。
首先定义一个属性类:
//单条属性类
publicclassXProp
{
privatestringtheId="";//属性Id,我的项目中需要,大家可以忽略
privatestringtheCategory="";//属性所属类别
privatestringtheName="";//属性名称
privatebooltheReadOnly=false;//属性的只读性,true为只读
privatestringtheDescription="";//属性的描述内容
privateobjecttheValue=null;//值
privateSystem.TypetheType=null;//类型
privatebooltheBrowsable=true;//显示或隐藏,true为显示
TypeConvertertheConverter=null;//类型转换
publicstringId
{
get{returntheId;}
set{theId=value;}
}
publicstringCategory
{
get{returntheCategory;}
set{theCategory=value;}
}
publicboolReadOnly
{
get{returntheReadOnly;}
set{theReadOnly=value;}
}
publicstringName
{
get{returnthis.theName;}
set{this.theName=value;}
}
publicobjectValue
{
get{returnthis.theValue;}
set{this.theValue=value;}
}
publicstringDescription
{
get{returntheDescription;}
set{theDescription=value;}
}
publicSystem.TypeProType
{
get{returntheType;}
set{theType=value;}
}
publicboolBrowsable
{
get{returntheBrowsable;}
set{theBrowsable=value;}
}
publicvirtualTypeConverterConverter
{
get{returntheConverter;}
set{theConverter=value;}
}
}
我举一个例子:
privatestringstrdemo;
[DescriptionAttribute("用于举例说明"),
CategoryAttribute("公有属性"),
DefaultValueAttribute(“测试属性”),
ReadOnlyAttribute(false),
BrowsableAttribute(true),
TypeConverter(typeof(MyComboTypeConvert))
]
public stringstrDemo
{
get { return strdemo; }
set { strdemo = value; }
}
这是个写死的属性,那在我的项目中,根据对象的不同,会需要生产不同的属性页,所以需要一个可以动态生成的属性页,将上述这个一般属性定义,利用XProp类,写成:
PrivateXPropnewXpro=newXProp();
newXpro.Category=”公有属性”;
newXpro.Name=”strDemo”;
newXpro.Id="A";
newXpro.Description=“用于举例说明”;
newXpro.ReadOnly=false;
newXpro.Value=“测试属性”;
newXpro.ProType=typeof(string);
newXpro.Browsable=true;
newXpro.Converter=null;
这样,一条属性就完成了。
当然你也可以根据需要自己重写更多的属性相关定义。
这里的Converter属性是在后面的下拉菜单中需要用到的,如果不是基础类型的(string,int,bool,enum等),我们可以赋值为null.
当然,这只是一条属性,原本按之前的方法,只要定义一个类,然后这个类里面定义多条属性就可以了。
但是现在,由于属性是动态生成的,我们并不能确定需要几个属性,也就不能直接在一个类里面定义完。
所以我们需要再定义一个List
先来定义以下两个类:
publicclassXProps:
List
{
#regionICustomTypeDescriptor成员
publicAttributeCollectionGetAttributes()
{
returnTypeDescriptor.GetAttributes(this,true);
}
publicstringGetClassName()
{
returnTypeDescriptor.GetClassName(this,true);
}
publicstringGetComponentName()
{
returnTypeDescriptor.GetComponentName(this,true);
}
publicTypeConverterGetConverter()
{
returnTypeDescriptor.GetConverter(this,true);
}
publicEventDescriptorGetDefaultEvent()
{
returnTypeDescriptor.GetDefaultEvent(this,true);
}
publicPropertyDescriptorGetDefaultProperty()
{
returnTypeDescriptor.GetDefaultProperty(this,true);
}
publicobjectGetEditor(System.TypeeditorBaseType)
{
returnTypeDescriptor.GetEditor(this,editorBaseType,true);
}
publicEventDescriptorCollectionGetEvents(System.Attribute[]attributes)
{
returnTypeDescriptor.GetEvents(this,attributes,true);
}
publicEventDescriptorCollectionGetEvents()
{
returnTypeDescriptor.GetEvents(this,true);
}
publicPropertyDescriptorCollectionGetProperties(System.Attribute[]attributes)
{
ArrayListprops=newArrayList();
for(inti=0;i { //判断属性是否显示 if(this[i].Browsable==true) { XPropDescriptorpsd=newXPropDescriptor(this[i],attributes); props.Add(psd); } } PropertyDescriptor[]propArray=(PropertyDescriptor[])props.ToArray(typeof(PropertyDescriptor)); returnnewPropertyDescriptorCollection(propArray); } publicPropertyDescriptorCollectionGetProperties() { returnTypeDescriptor.GetProperties(this,true); } publicobjectGetPropertyOwner(PropertyDescriptorpd) { returnthis; } #endregion publicoverridestringToString() { StringBuildersb=newStringBuilder(); for(inti=0;i { sb.Append("["+i+"]"+this[i].ToString()+System.Environment.NewLine); } returnsb.ToString(); } } privateclassXPropDescriptor: PropertyDescriptor { XProptheProp; publicXPropDescriptor(XPropprop,Attribute[]attrs) : base(prop.Name,attrs) { theProp=prop; } publicoverrideboolCanResetValue(objectcomponent) { returnfalse; } publicoverridestringCategory { get{returntheProp.Category;} } publicoverridestringDescription { get{returntheProp.Description;} } publicoverrideTypeConverterConverter { get{returntheProp.Converter;} } publicoverrideSystem.TypeComponentType { get{returnthis.GetType();} } publicoverrideobjectGetValue(objectcomponent) { returntheProp.Value; } publicoverrideboolIsReadOnly { get{returntheProp.ReadOnly;} } publicoverrideSystem.TypePropertyType { get{returntheProp.ProType;} } publicoverridevoidResetValue(objectcomponent) { } publicoverridevoidSetValue(objectcomponent,objectvalue) { theProp.Value=value; } publicoverrideboolShouldSerializeValue(objectcomponent) { returnfalse; } } 然后我们新声明一个属性列表: PrivateXPropsxprops=newXProps(); //再将刚刚那个动态生成的属性添加进去,将属性页的selectobject赋值为这个类: xprops.add(newXpro); PropertyGridDemo.SelectedObject=xprops; 现在我们来看看效果: 根据需要,你可以添加多条属性。 也许你会想问,这里哪有动态生成啊,那些属性名称,属性类型什么的不还是写死的么。 呵呵,我这里只是举个例子所以写死了,在实际应用中,你可以根据需要,在生成属性列表的时候,动态赋值,例如你是从xml文件里读取到的,例如你是从服务器中获取到的。 根据你读取的对象,一个一个赋值就可以了。 下面来介绍如何在属性页中动态生成下拉菜单框,关于下拉菜单真的是很复杂,在.net的PropertyGrid控件中,想要具有下拉菜单的属性,简单的可以通过枚举类型来实现,还是以刚刚的那个例子来说明: 首先定义个枚举类型: publicenumenumType { BOOLVAL, DIGITALVAL, STRINGVAL, CHECKVAL, RATIOVAL, IPVAL, COMBOBOX, RESETBTN } 然后代码中将属性值与属性类型修改为: newXpro.Value=CustomClass.enumType.BOOLVAL;//这里的属性值当然必须为枚举中的某一项 newXpro.ProType=typeof(enumType); 然后我们来看看实现的效果: 这就是最简单的下拉菜单的实现方式了。 但是这里的枚举类型仍然是需要代码中写死的,而我在网上也所搜了很久,枚举类型似乎没办法动态生成,如果要实现动态生成恐怕要另寻他途。 所幸的是,我曾经见过重写combobox来生成属性页的下来菜单的,我们需要定义: //重写下拉菜单中的项,使之与属性页的项关联 publicabstractclassComboBoxItemTypeConvert: TypeConverter { publicHashtablemyhash=null; publicComboBoxItemTypeConvert() { myhash=newHashtable(); GetConvertHash(); } publicabstractvoidGetConvertHash(); //是否支持选择列表的编辑 publicoverrideboolGetStandardValuesSupported(ITypeDescriptorContextcontext) { returntrue; } //重写combobox的选择列表 publicoverrideStandardValuesCollectionGetStandardValues(ITypeDescriptorContextcontext) { int[]ids=newint[myhash.Values.Count]; inti=0; foreach(DictionaryEntrymyDEinmyhash) { ids[i++]=(int)(myDE.Key); } returnnewStandardValuesCollection(ids); } //判断转换器是否可以工作 publicoverrideboolCanConvertFrom(ITypeDescriptorContextcontext,TypesourceType) { if(sourceType==typeof(string)) { returntrue; } returnbase.CanConvertFrom(context,sourceType); } //重写转换器,将选项列表(即下拉菜单)中的值转换到该类型的值 publicoverrideobjectConvertFrom(ITypeDescriptorContextcontext,System.Globalization.CultureInfoculture,objectobj) { if(objisstring) { foreach(DictionaryEntrymyDEinmyhash) { if(myDE.Value.Equals((obj.ToString()))) returnmyDE.Key; } } returnbase.ConvertFrom(context,culture,obj); } publicoverrideboolCanConvertTo(ITypeDescriptorContextcontext,TypedestinationType) { if(destinationType==typeof(string)) { returntrue; } returnbase.CanConvertTo(context,destinationType); } //重写转换器将该类型的值转换到选择列表中 publicoverrideobjectConvertTo(ITypeDescriptorContextcontext,System.Globalization.CultureInfoculture,objectobj,TypedestinationType) { if(destinationType==typeof(string)) { foreach(DictionaryEntrymyDEinmyhash) { if(myDE.Key.Equals(obj)) returnmyDE.Value.ToString(); } return""; } returnbase.ConvertTo(context,culture,obj,destinationType); } publicoverrideboolGetStandardValuesExclusive(ITypeDescriptorContextcontext) { returnfalse; } } //重写下拉菜单,在这里实现定义下拉菜单内的项 publicclassMyComboItemConvert: ComboBoxItemTypeConvert { privateHashtablehash; publicoverridevoidGetConvertHash() { try { myhash=hash; } catch { thrownewNotImplementedException(); } } publicMyComboItemConvert(stringstr) { hash=newHashtable(); string[]stest=str.Split(','); for(inti=0;i { hash.Add(i,stest[i]); } GetConvertHash(); value=0; } publicintvalue{get;set;} publicMyComboItemConvert(stringstr,ints) { hash=newHashtable(); string[]stest=str.Split(','); for(inti=0;i { hash.Add(i,stest[i]); } GetConvertHash(); value=s; } } 在这里你可以看到,MyComboItemConvert有两个重载,分别有不同的参数,其中string类型的那个参数就是用于获取下拉菜单的项的。 当然你也可以根据需要定义为其他类型的,例如List或是HashTable。 只要在函数中将下拉菜单的每一项放入哈希表中就可以了。 而在生成的代码中,我们就需要用到刚刚没有使用的Converter属性了: 举个例子: XPropsxps=newXProps(); XPropxprop=newXProp(); xprop.Name="姓名"; xprop.Value="某人; xprop.Category="人类"; xprop.Description="姓甚名谁"; xprop.ProType=typeof(String); xprop.ReadOnly=true; xps.Add(xprop); xprop=newXProp(); xprop.Category="人类"; xprop.Name="年龄"; xprop.ProType=typeof(int); xprop.Value="2"; xprop.Description="多大年纪"; xprop.ReadOnly=false; xps.Add(xprop); xprop=newXProp(); xprop.Category="人类"; xprop.Name="性别"; xprop.Value=1; xprop.ReadOnly=false; xprop.ProType=typeof(CustomClass.MyComboItemCo
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- net PropertyGrid动态生成属性页 PropertyGrid 动态 生成 属性