既然是一个窗体设计器,那就应该能够设置控件的属性,设置属性最好的当然是PropertyGrid了,我们仅仅需要使用一个PropertyGrid.SelectedObject = Control就可以搞定,让PropertyGrid显示Control的所有属性。可是这里显示的属性名是英文的。对于我们开发人员来说这无可厚非,我们也乐于接受。并且让PropertyGrid显示中文属性名,这对于我们开发人员的使用来说显得多此一举。可是,对于我这种类型的一个应用工具,英文属性名对于很多客户来说可能就很难懂了。所以应该让PrpertyGrid能够显示中文属性名。
如图:
另外,对于这样的一个系统。并不是控件的所有属性都是用户希望的,可能用户希望看到的仅仅是控件高度、控件宽度、控件文本。。等等的属性,但是如果直接将一个控件属性全部显示给用户的话,估计对用户造成的干扰和困惑是很大的。如何解决这个问题呢?其实用户控件开发的时候,如果我们不希望此属性在PropertyGrid中显示,我们可以设置这个控件的Attribute,如:
[Browsable(false)]<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
public int Width
{
get { }
set { }
}
通过使用BrowsableAttribute就可以设置将此属性对PropertyGrid隐藏。
你可能要问到了,对于控件来说,其中的很多属性都是直接继承来的,我们并没有办法控制是否对PropertyGrid隐藏啊?呵呵,对啊,这就是我下面要说的解决方法(当然此方法显得不是很灵活,但是对于这种类型的系统的确相当有用)。
在我的解决方式中,我不直接这样PropertyGrid.SelectedObject = Control,而是把这个Control替换成一个专门为此类型的Control设计的类对象上。比如我对TextBox设计了一个TextBoxProperty,这样我们使用的是PropertyGrid.SelectedObject = TextBoxProperty的一个对象。
下面就是TextBoxProperty的代码:
- publicclassTextBoxProperty:PropertyBase
- {
- privateTextBox_Control;
- publicTextBoxProperty()
- {
- }
- publicTextBoxProperty(TextBoxcontrol)
- {
- this._Control=control;
- }
- [MyControlAttibute("文本","获取或者设置控件文本","")]
- publicstringText
- {
- get{returnthis._Control.Text;}
- set
- {
- this._Control.Text=value;
- }
- }
- [MyControlAttibute("宽度","获取或者设置控件宽度","")]
- publicintWidth
- {
- get{returnthis._Control.Width;}
- set
- {
- this._Control.Width=(int)value;
- }
- }
- [MyControlAttibute("高度","获取或者设置控件高度","")]
- publicintHeight
- {
- get{returnthis._Control.Height;}
- set
- {
- this._Control.Height=(int)value;
- }
- }
- [MyControlAttibute("上边距","获取或者设置控件上边位置","")]
- publicintTop
- {
- get{returnthis._Control.Top;}
- set
- {
- this._Control.Top=value;
- }
- }
- [MyControlAttibute("左边距","获取或者设置控件左边位置","")]
- publicintLeft
- {
- get{returnthis._Control.Left;}
- set
- {
- this._Control.Left=value;
- }
- }
- [MyControlAttibute("背景色","获取或者设置控件背景颜色","")]
- publicColorBackColor
- {
- get{returnthis._Control.BackColor;}
- set
- {
- this._Control.BackColor=value;
- }
- }
- [MyControlAttibute("前景色","获取或者设置控件的前景颜色","")]
- publicColorForeColor
- {
- get{returnthis._Control.ForeColor;}
- set
- {
- this._Control.ForeColor=value;
- }
- }
- }
你从代码里面已经看出了一些端倪了,在TextBoxProperty中每个要属性都增加了MyControlAttibute,具体Attribute的概念和使用方法您可以参考我的另一篇Blog文《C#基础系列:实现自己的ORM(反射以及Attribute在ORM中的应用)》。这里对Attribute做了详细的介绍(对初学者有效)。所以我就直接贴出MyControlAttibute的代码好了:
- publicclassMyControlAttibute:Attribute
- {
- privatestring_PropertyName;
- privatestring_PropertyDescription;
- privateobject_DefaultValue;
- publicMyControlAttibute(stringName,stringDescription,objectDefalutValue)
- {
- this._PropertyName=Name;
- this._PropertyDescription=Description;
- this._DefaultValue=DefalutValue;
- }
- publicMyControlAttibute(stringName,stringDescription)
- {
- this._PropertyName=Name;
- this._PropertyDescription=Description;
- this._DefaultValue="";
- }
- publicMyControlAttibute(stringName)
- {
- this._PropertyName=Name;
- this._PropertyDescription="";
- this._DefaultValue="";
- }
- publicstringPropertyName
- {
- get{returnthis._PropertyName;}
- }
- publicstringPropertyDescription
- {
- get{returnthis._PropertyDescription;}
- }
- publicobjectDefaultValue
- {
- get{returnthis._DefaultValue;}
- }
- }
通过上面的两段代码,你已经初步看出了在PropertyGrid中显示中文属性以及仅仅显示我们需要的属性的基本思路。下面就介绍的就是怎么让MyControlAttibute中定义了的中文属性名在PropertyGrid中显示出来。下面这段代码,我仅仅贡献了PropertyStub中这个函数的实现。所以不做过多解释了:
- publicoverridestringDisplayName
- {
- get
- {
- if(info!=null)
- {
- MyControlAttibuteuicontrolattibute=(MyControlAttibute)Attribute.GetCustomAttribute(info,typeof(MyControlAttibute));
- if(uicontrolattibute!=null)
- returnuicontrolattibute.PropertyName;
- else
- {
- returninfo.Name;
- }
- }
- else
- return"";
- }
- }
整个代码如下,里面包含两个类,你直接拷贝出来就可以使用了:
- publicdelegatevoidPropertyChanged(objectValue);
-
-
-
- publicclassPropertyBase:ICustomTypeDescriptor
- {
-
-
-
-
- #regionICustomTypeDescriptor显式接口定义
- AttributeCollectionICustomTypeDescriptor.GetAttributes()
- {
- returnTypeDescriptor.GetAttributes(this,true);
- }
- stringICustomTypeDescriptor.GetClassName()
- {
- returnTypeDescriptor.GetClassName(this,true);
- }
- stringICustomTypeDescriptor.GetComponentName()
- {
- returnTypeDescriptor.GetComponentName(this,true);
- }
- TypeConverterICustomTypeDescriptor.GetConverter()
- {
- returnTypeDescriptor.GetConverter(this,true);
- }
- EventDescriptorICustomTypeDescriptor.GetDefaultEvent()
- {
- returnTypeDescriptor.GetDefaultEvent(this,true);
- }
- PropertyDescriptorICustomTypeDescriptor.GetDefaultProperty()
- {
- returnnull;
- }
- objectICustomTypeDescriptor.GetEditor(TypeeditorBaseType)
- {
- returnTypeDescriptor.GetEditor(this,editorBaseType,true);
- }
- EventDescriptorCollectionICustomTypeDescriptor.GetEvents()
- {
- returnTypeDescriptor.GetEvents(this,true);
- }
- EventDescriptorCollectionICustomTypeDescriptor.GetEvents(Attribute[]attributes)
- {
- returnTypeDescriptor.GetEvents(this,attributes,true);
- }
- PropertyDescriptorCollectionICustomTypeDescriptor.GetProperties()
- {
- return((ICustomTypeDescriptor)this).GetProperties(newAttribute[0]);
- }
- PropertyDescriptorCollectionICustomTypeDescriptor.GetProperties(Attribute[]attributes)
- {
- ArrayListprops=newArrayList();
- TypethisType=this.GetType();
- PropertyInfo[]pis=thisType.GetProperties();
- foreach(PropertyInfopinpis)
- {
- if(p.DeclaringType==thisType||p.PropertyType.ToString()=="System.Drawing.Color")
- {
-
- BrowsableAttributeBrowsable=(BrowsableAttribute)Attribute.GetCustomAttribute(p,typeof(BrowsableAttribute));
- if(Browsable!=null)
- {
- if(Browsable.Browsable==true||p.PropertyType.ToString()=="System.Drawing.Color")
- {
- PropertyStubpsd=newPropertyStub(p,attributes);
- props.Add(psd);
- }
- }
- else
- {
- PropertyStubpsd=newPropertyStub(p,attributes);
- props.Add(psd);
- }
- }
- }
- PropertyDescriptor[]propArray=(PropertyDescriptor[])props.ToArray(typeof(PropertyDescriptor));
- returnnewPropertyDescriptorCollection(propArray);
- }
- objectICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptorpd)
- {
- returnthis;
- }
- #endregion
- }
-
-
-
- #regionPropertyStub定义
- publicclassPropertyStub:PropertyDescriptor
- {
- PropertyInfoinfo;
- publicPropertyStub(PropertyInfopropertyInfo,Attribute[]attrs)
- :base(propertyInfo.Name,attrs)
- {
- this.info=propertyInfo;
- }
- publicoverrideTypeComponentType
- {
- get{returnthis.info.ReflectedType;}
- }
- publicoverrideboolIsReadOnly
- {
- get{returnthis.info.CanWrite==false;}
- }
- publicoverrideTypePropertyType
- {
- get{returnthis.info.PropertyType;}
- }
- publicoverrideboolCanResetValue(objectcomponent)
- {
- returnfalse;
- }
- publicoverrideobjectGetValue(objectcomponent)
- {
-
- try
- {
- returnthis.info.GetValue(component,null);
- }
- catch
- {
- returnnull;
- }
- }
- publicoverridevoidResetValue(objectcomponent)
- {
- }
- publicoverridevoidSetValue(objectcomponent,objectvalue)
- {
-
- this.info.SetValue(component,value,null);
- }
- publicoverrideboolShouldSerializeValue(objectcomponent)
- {
- returnfalse;
- }
-
- publicoverridestringDisplayName
- {
- get
- {
- if(info!=null)
- {
- MyControlAttibuteuicontrolattibute=(MyControlAttibute)Attribute.GetCustomAttribute(info,typeof(MyControlAttibute));
- if(uicontrolattibute!=null)
- returnuicontrolattibute.PropertyName;
- else
- {
- returninfo.Name;
- }
- }
- else
- return"";
- }
- }
- }
- #endregion
修改后的Form界面如下:
Form中由于我仅仅是演示了TextBox所以我就是直接将创建TextBoxProperty对象的代码放在了Control_Click中:
//我这里仅仅做TextBox的属性演示,如果是其它的控件的话,那么你需要设计不同的ControlProperty(比如TextBoxProperty,ComboBoxProperty)
if (sender is TextBox)
{
this.propertyGrid1.SelectedObject = new TextBoxProperty((TextBox)sender);
}
else
{
this.propertyGrid1.SelectedObject = null;
}
对于实际的需要来说应该是根据Control的类型,通过工厂模式来创建ControlProperty。
Form的整个代码如下,窗体如上图所示:
-
- publicpartialclassForm1:Form
- {
- privateMouseHook_MouseHook;
-
- privateHashtable_HashUISizeKnob;
-
- privateHashtable_HashUIMoveKnob;
- publicForm1()
- {
- InitializeComponent();
- this._MouseHook=newMouseHook(this);
- this._HashUISizeKnob=newHashtable();
- this._HashUIMoveKnob=newHashtable();
-
- this.ControlAdded+=newControlEventHandler(Form1_ControlAdded);
- }
- voidForm1_ControlAdded(objectsender,ControlEventArgse)
- {
- if(!(e.ControlisUISizeDot))
- {
- this._HashUISizeKnob.Add(e.Control,newUISizeKnob(e.Control));
- this._HashUIMoveKnob.Add(e.Control,newUIMoveKnob(e.Control));
-
- e.Control.Click+=newEventHandler(Control_Click);
- }
- }
- voidControl_Click(objectsender,EventArgse)
- {
-
- foreach(UISizeKnobknobinthis._HashUISizeKnob.Values)
- {
- knob.ShowUISizeDots(false);
- }
-
-
- try
- {
- ((UISizeKnob)this._HashUISizeKnob[sender]).ShowUISizeDots(true);
-
- if(senderisTextBox)
- {
- this.propertyGrid1.SelectedObject=newTextBoxProperty((TextBox)sender);
- }
- else
- {
- this.propertyGrid1.SelectedObject=null;
- }
- }
- catch{}
- }
- privatevoidcmdArrow_Click(objectsender,EventArgse)
- {
- SettingService.Instance.SelectedToolBoxControl=null;
- }
- privatevoidcmdLabel_Click(objectsender,EventArgse)
- {
- SettingService.Instance.SelectedToolBoxControl=newLabel();
- }
- privatevoidcmdTextBox_Click(objectsender,EventArgse)
- {
- SettingService.Instance.SelectedToolBoxControl=newTextBox();
- }
- privatevoidcmdComboBox_Click(objectsender,EventArgse)
- {
- SettingService.Instance.SelectedToolBoxControl=newComboBox();
- }
- privatevoidcmdGroupBox_Click(objectsender,EventArgse)
- {
- SettingService.Instance.SelectedToolBoxControl=newGroupBox();
- }
- }
好了,让
PropertyGrid
显示中文属性的思路和代码都给了,希望能够给你点启发和帮助。
相关文章:
C#基础系列:开发自己的窗体设计器(总纲)
C#基础系列:开发自己的窗体设计器(在容器上拖动鼠标增加控件)
C#基础系列:开发自己的窗体设计器(实现控件的选择)
C#基础系列:开发自己的窗体设计器(实现控件的拖动)