修改自定义类中属性的可见性问题(动态增减类的属性个数)

问题描述

之前发了一个帖子问题描述的太简单了给大家造成了误解这里重新开贴详细说明出于项目要求需要定义一个属性可以动态增加的类(比如说定义一个截面类,包含形状、半径、长度、宽度四个属性,其中形状枚举圆形和矩形两种,选择圆形时显示半径属性不显示长宽属性,选择矩形时显示长宽属性不显示半径属性。也就是说利用PropertyGrid控件展示该类的属性是,当选择圆形时PropertyGrid可以显示2个属性,选择矩形时PropertyGrid则显示3个属性,无论2个属性还是3个属性对应的是同一个实例)于是在网上找到的SetPropertyVisability函数可以对截面类的一个实例实现我要的功能。但是当我定义2个截面实例的时候,一个设为圆形一个设为矩形行,由于SetPropertyVisability函数利用了反射,所以当其中任意一个实例被修改,2个实例的可见属性个数永远一致,并由最后一次对某一实例的形状进行更改是的数值决定。这是我不希望的。有没有大神知道解决方法,谢谢了(分别建成2个类的改动太大了)下面贴代码和图说明问题类代码enumfaceType{circ,rect}classface{privatefaceTypeft=faceType.circ;[Category("类型"),Description("截面形状"),ReadOnlyAttribute(false),BrowsableAttribute(true)]publicfaceTypeFaceType{get{returnft;}set{ft=value;if(ft==faceType.circ){SetPropertyVisability(this,"R",true);SetPropertyVisability(this,"L",false);SetPropertyVisability(this,"W",false);}else{SetPropertyVisability(this,"R",false);SetPropertyVisability(this,"L",true);SetPropertyVisability(this,"W",true);}}}privateintr=0;[Category("数据"),Description("半径"),ReadOnlyAttribute(false),BrowsableAttribute(true)]publicintR{get{returnr;}set{r=value;}}privateintl=0;[Category("数据"),Description("长度"),ReadOnlyAttribute(false),BrowsableAttribute(false)]publicintL{get{returnl;}set{l=value;}}privateintw=0;[Category("数据"),Description("宽度"),ReadOnlyAttribute(false),BrowsableAttribute(false)]publicintW{get{returnw;}set{w=value;}}///<summary>设置属性的可见性</summary>/// <param name="obj">属性所属的类</param>/// <param name="propertyName">属性名</param>/// <param name="visable">可见性</param>publicvoidSetPropertyVisability(objectobj,stringpropertyName,boolvisable){Typetype=typeof(System.ComponentModel.BrowsableAttribute);PropertyDescriptorCollectionprops=TypeDescriptor.GetProperties(obj);AttributeCollectionattrs=props[propertyName].Attributes;FieldInfofld=type.GetField("browsable",BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.CreateInstance);fld.SetValue(attrs[type],visable);}}

界面代码publicpartialclassForm1:Form{publicForm1(){InitializeComponent();}facea=newface();faceb=newface();privatevoidForm1_Load(objectsender,EventArgse){propertyGrid1.SelectedObject=a;propertyGrid2.SelectedObject=b;}privatevoidpropertyGrid1_PropertyValueChanged(objects,PropertyValueChangedEventArgse){propertyGrid1.SelectedObject=a;propertyGrid2.SelectedObject=b;}}

运行界面(初始默认为圆形)然后我讲左边PropertyGrid中的形状改为矩形,右边的与跟着变了。我希望右边的不要跟着变。求大神指点啊100分啊解决了再送100分

解决方案

解决方案二:
本身设计有问题,以后加个三角形怎么办,矩形为什么有半径?
解决方案三:
我觉得可以用嵌套类,根据类型实例化特定的类,不一致的不实例化它然后属性里用个泛型来引用这个类
解决方案四:
为什么不能System.Reflection.Emit命名空间的一些类,动态创建类及其拥有的属性.
解决方案五:
既然用到了TypeDescriptor,那就还是基于这个体系,继承一个TypeDescriptionProvider和CustomTypeDescriptor,用默认的作为parent,overrideGetProperties方法,里面根据需要过滤属性,使用TypeDescriptor.AddProvider对那个类型添加自己的这个provider就可以了。
解决方案六:
既然是面向对象编程,就要合理使用继承(也就是建不同的类),至于改动有多大,不懂真正的面向对象编程的人是不知道的.
解决方案七:
PropertyGrid本身就可以编码实现哪些显示,哪些不显示。——这个里面的PropertyGrid就是动态生成的。
解决方案八:
核心代码懒得找了。自己下载Demo看吧。上面的匹配引擎介绍:http://www.shuxiaolong.com/Project/0/5I7UFN38GEQ.aspx上面的匹配引擎下载:http://www.shuxiaolong.com/DoAjax/DownloadHandler.ashx?Number=5I7UG4TJGY4

时间: 2024-09-04 12:59:13

修改自定义类中属性的可见性问题(动态增减类的属性个数)的相关文章

c++-为什么在类中定义没有定义默认构造函数的类类型变量通过编译了?

问题描述 为什么在类中定义没有定义默认构造函数的类类型变量通过编译了? class T { public: T(int i) :_i(i) {} private: int _i; }; class U { private: T t; }; 如果定义了一个构造函数不是就会取消合成的默认构造函数吗? 可以定义不可以赋值是吧?刚才发现 const int ci; int &ri; 也通过编译了. 解决方案 语法这么规定的,因为t是成员变量 如果你写在函数里 main() { T t; } 那就报错了.

jpg-在MFC的CDialog类中可以显示JPG图片 在CFromview类中用同样的方法显示不了

问题描述 在MFC的CDialog类中可以显示JPG图片 在CFromview类中用同样的方法显示不了 HGLOBAL hMem; IStream *m_pStream; IPicture *m_pPicture; OLE_XSIZE_HIMETRIC m_JPGWidth; OLE_XSIZE_HIMETRIC m_JPGHeight; CRect rect(100,120,600,460); CString path; CFile file; CFileDialog dlg(TRUE,_T(

java代码-java初学者提问 在类中 用static成员变量实例化自身类 程序的执行顺序过程是怎样的?

问题描述 java初学者提问 在类中 用static成员变量实例化自身类 程序的执行顺序过程是怎样的? class Demo03 { public static void main(String[] args) { A.show(); } } class A { //构造方法 A(){ System.out.println("构造方法执行"); System.out.println(b); System.out.println(c); } static A a=new A(); sta

为什么Array类中的Add(..)方法和Count属性不可见呢?

问题描述 为什么Array类中的Add(..)方法和Count属性不可见呢?.Framework中是如下定义的:classArray:ICollection,IList{......}interfaceICollection{intAdd(..);}interfaceIList:ICollection{intCount{get;}}我查了msdn,发现add()和Count在Array类中是私有的,难道Array类实现ICollection和IList这两个接口的Add(..)方法和Count属

深入分析C++派生类中的保护成员继承_C 语言

protected 与 public 和 private 一样是用来声明成员的访问权限的.由protected声明的成员称为"受保护的成员",或简称"保护成员".从类的用户角度来看,保护成员等价于私有成员.但有一点与私有成员不同,保护成员可以被派生类的成员函数引用. 如果基类声明了私有成员,那么任何派生类都是不能访问它们的,若希望在派生类中能访问它们,应当把它们声明为保护成员.如果在一个类中声明了保护成员,就意味着该类可能要用作基类,在它的派生类中会访问这些成员.

java 初始化 对象-导出类中默认创建基类的子对象

问题描述 导出类中默认创建基类的子对象 读<Java编程思想第四版>第7章复用类,7.2.1初始化基类中, 描述当创建一个导出类对象的时候会自动创建一个基类子对象. 那如果我继承自一个抽象类,那么编译器会怎么处理呢? 解决方案 抽象类是不能实例化的,基类的构造函数只是设置了这个类的属性等,这个对象是一个子类的对象,只是可以用父类指向它而已. 也就是说创建一个子类的时候,没有创建两个对象,而是一个对象.

ios-在继承类中调用方法报错

问题描述 在继承类中调用方法报错 有两个类A和B.在A类中: @interface A : B 在B类中,得到如下代码: self.navigationItem.rightBarButtonItem = [UIBarButtonItem barItemWithImage:[UIImage imageNamed:@""Add-button-normal""] highlightedImage:[UIImage imageNamed:@""Add-b

如何在rest类中获取httpservletrequest对象

问题描述 如何在rest类中获取httpservletrequest对象 如何在rest类中获取httpservletrequest对象,在网上找的大部分都不好用,求高手帮帮忙,谢了 解决方案 看你的rest类怎么定义的,上下文是什么,如果你一窍不通,还是找个略懂程序的学生帮你下.写程序这件事不是word打字,不是网上胡乱找个代码一贴就能好用的.

第8周-任务3-实现分数类中的运算符重载

[题目]实现分数类中的运算符重载,在分数类中可以完成分数的加减乘除(运算后再化简).求反.比较(6种关系)的运算. class CFraction { private: int nume; // 分子 int deno; // 分母 public: //构造函数及运算符重载的函数声明 }; //重载函数的实现及用于测试的main()函数 [参考解答] #include <iostream> using namespace std; class CFraction { private: int