`
saybody
  • 浏览: 904386 次
  • 性别: Icon_minigender_2
  • 来自: 西安
文章分类
社区版块
存档分类
最新评论

C#基础系列:开发自己的窗体设计器(PropertyGrid显示中文属性名)

阅读更多

既然是一个窗体设计器,那就应该能够设置控件的属性,设置属性最好的当然是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的代码:

  1. publicclassTextBoxProperty:PropertyBase
  2. {
  3. privateTextBox_Control;
  4. publicTextBoxProperty()
  5. {
  6. }
  7. publicTextBoxProperty(TextBoxcontrol)
  8. {
  9. this._Control=control;
  10. }
  11. [MyControlAttibute("文本","获取或者设置控件文本","")]
  12. publicstringText
  13. {
  14. get{returnthis._Control.Text;}
  15. set
  16. {
  17. this._Control.Text=value;
  18. }
  19. }
  20. [MyControlAttibute("宽度","获取或者设置控件宽度","")]
  21. publicintWidth
  22. {
  23. get{returnthis._Control.Width;}
  24. set
  25. {
  26. this._Control.Width=(int)value;
  27. }
  28. }
  29. [MyControlAttibute("高度","获取或者设置控件高度","")]
  30. publicintHeight
  31. {
  32. get{returnthis._Control.Height;}
  33. set
  34. {
  35. this._Control.Height=(int)value;
  36. }
  37. }
  38. [MyControlAttibute("上边距","获取或者设置控件上边位置","")]
  39. publicintTop
  40. {
  41. get{returnthis._Control.Top;}
  42. set
  43. {
  44. this._Control.Top=value;
  45. }
  46. }
  47. [MyControlAttibute("左边距","获取或者设置控件左边位置","")]
  48. publicintLeft
  49. {
  50. get{returnthis._Control.Left;}
  51. set
  52. {
  53. this._Control.Left=value;
  54. }
  55. }
  56. [MyControlAttibute("背景色","获取或者设置控件背景颜色","")]
  57. publicColorBackColor
  58. {
  59. get{returnthis._Control.BackColor;}
  60. set
  61. {
  62. this._Control.BackColor=value;
  63. }
  64. }
  65. [MyControlAttibute("前景色","获取或者设置控件的前景颜色","")]
  66. publicColorForeColor
  67. {
  68. get{returnthis._Control.ForeColor;}
  69. set
  70. {
  71. this._Control.ForeColor=value;
  72. }
  73. }
  74. }

你从代码里面已经看出了一些端倪了,在TextBoxProperty中每个要属性都增加了MyControlAttibute,具体Attribute的概念和使用方法您可以参考我的另一篇Blog文《C#基础系列:实现自己的ORM(反射以及AttributeORM中的应用)》。这里对Attribute做了详细的介绍(对初学者有效)。所以我就直接贴出MyControlAttibute的代码好了:

  1. publicclassMyControlAttibute:Attribute
  2. {
  3. privatestring_PropertyName;
  4. privatestring_PropertyDescription;
  5. privateobject_DefaultValue;
  6. publicMyControlAttibute(stringName,stringDescription,objectDefalutValue)
  7. {
  8. this._PropertyName=Name;
  9. this._PropertyDescription=Description;
  10. this._DefaultValue=DefalutValue;
  11. }
  12. publicMyControlAttibute(stringName,stringDescription)
  13. {
  14. this._PropertyName=Name;
  15. this._PropertyDescription=Description;
  16. this._DefaultValue="";
  17. }
  18. publicMyControlAttibute(stringName)
  19. {
  20. this._PropertyName=Name;
  21. this._PropertyDescription="";
  22. this._DefaultValue="";
  23. }
  24. publicstringPropertyName
  25. {
  26. get{returnthis._PropertyName;}
  27. }
  28. publicstringPropertyDescription
  29. {
  30. get{returnthis._PropertyDescription;}
  31. }
  32. publicobjectDefaultValue
  33. {
  34. get{returnthis._DefaultValue;}
  35. }
  36. }

通过上面的两段代码,你已经初步看出了在PropertyGrid中显示中文属性以及仅仅显示我们需要的属性的基本思路。下面就介绍的就是怎么让MyControlAttibute中定义了的中文属性名在PropertyGrid中显示出来。下面这段代码,我仅仅贡献了PropertyStub中这个函数的实现。所以不做过多解释了:

  1. publicoverridestringDisplayName
  2. {
  3. get
  4. {
  5. if(info!=null)
  6. {
  7. MyControlAttibuteuicontrolattibute=(MyControlAttibute)Attribute.GetCustomAttribute(info,typeof(MyControlAttibute));
  8. if(uicontrolattibute!=null)
  9. returnuicontrolattibute.PropertyName;
  10. else
  11. {
  12. returninfo.Name;
  13. }
  14. }
  15. else
  16. return"";
  17. }
  18. }

整个代码如下,里面包含两个类,你直接拷贝出来就可以使用了:

  1. publicdelegatevoidPropertyChanged(objectValue);
  2. ///<summary>
  3. ///主要是实现中文化属性显示
  4. ///</summary>
  5. publicclassPropertyBase:ICustomTypeDescriptor
  6. {
  7. ///<summary>
  8. ///下面这段代码来源于:http://www.bluespace.cn/Html/Csdn/2_47/View_4702219.html
  9. ///</summary>
  10. ///<returns></returns>
  11. #regionICustomTypeDescriptor显式接口定义
  12. AttributeCollectionICustomTypeDescriptor.GetAttributes()
  13. {
  14. returnTypeDescriptor.GetAttributes(this,true);
  15. }
  16. stringICustomTypeDescriptor.GetClassName()
  17. {
  18. returnTypeDescriptor.GetClassName(this,true);
  19. }
  20. stringICustomTypeDescriptor.GetComponentName()
  21. {
  22. returnTypeDescriptor.GetComponentName(this,true);
  23. }
  24. TypeConverterICustomTypeDescriptor.GetConverter()
  25. {
  26. returnTypeDescriptor.GetConverter(this,true);
  27. }
  28. EventDescriptorICustomTypeDescriptor.GetDefaultEvent()
  29. {
  30. returnTypeDescriptor.GetDefaultEvent(this,true);
  31. }
  32. PropertyDescriptorICustomTypeDescriptor.GetDefaultProperty()
  33. {
  34. returnnull;
  35. }
  36. objectICustomTypeDescriptor.GetEditor(TypeeditorBaseType)
  37. {
  38. returnTypeDescriptor.GetEditor(this,editorBaseType,true);
  39. }
  40. EventDescriptorCollectionICustomTypeDescriptor.GetEvents()
  41. {
  42. returnTypeDescriptor.GetEvents(this,true);
  43. }
  44. EventDescriptorCollectionICustomTypeDescriptor.GetEvents(Attribute[]attributes)
  45. {
  46. returnTypeDescriptor.GetEvents(this,attributes,true);
  47. }
  48. PropertyDescriptorCollectionICustomTypeDescriptor.GetProperties()
  49. {
  50. return((ICustomTypeDescriptor)this).GetProperties(newAttribute[0]);
  51. }
  52. PropertyDescriptorCollectionICustomTypeDescriptor.GetProperties(Attribute[]attributes)
  53. {
  54. ArrayListprops=newArrayList();
  55. TypethisType=this.GetType();
  56. PropertyInfo[]pis=thisType.GetProperties();
  57. foreach(PropertyInfopinpis)
  58. {
  59. if(p.DeclaringType==thisType||p.PropertyType.ToString()=="System.Drawing.Color")
  60. {
  61. //判断属性是否显示
  62. BrowsableAttributeBrowsable=(BrowsableAttribute)Attribute.GetCustomAttribute(p,typeof(BrowsableAttribute));
  63. if(Browsable!=null)
  64. {
  65. if(Browsable.Browsable==true||p.PropertyType.ToString()=="System.Drawing.Color")
  66. {
  67. PropertyStubpsd=newPropertyStub(p,attributes);
  68. props.Add(psd);
  69. }
  70. }
  71. else
  72. {
  73. PropertyStubpsd=newPropertyStub(p,attributes);
  74. props.Add(psd);
  75. }
  76. }
  77. }
  78. PropertyDescriptor[]propArray=(PropertyDescriptor[])props.ToArray(typeof(PropertyDescriptor));
  79. returnnewPropertyDescriptorCollection(propArray);
  80. }
  81. objectICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptorpd)
  82. {
  83. returnthis;
  84. }
  85. #endregion
  86. }
  87. ///<summary>
  88. ///下面这段代码来源于:http://www.bluespace.cn/Html/Csdn/2_47/View_4702219.html
  89. ///</summary>
  90. #regionPropertyStub定义
  91. publicclassPropertyStub:PropertyDescriptor
  92. {
  93. PropertyInfoinfo;
  94. publicPropertyStub(PropertyInfopropertyInfo,Attribute[]attrs)
  95. :base(propertyInfo.Name,attrs)
  96. {
  97. this.info=propertyInfo;
  98. }
  99. publicoverrideTypeComponentType
  100. {
  101. get{returnthis.info.ReflectedType;}
  102. }
  103. publicoverrideboolIsReadOnly
  104. {
  105. get{returnthis.info.CanWrite==false;}
  106. }
  107. publicoverrideTypePropertyType
  108. {
  109. get{returnthis.info.PropertyType;}
  110. }
  111. publicoverrideboolCanResetValue(objectcomponent)
  112. {
  113. returnfalse;
  114. }
  115. publicoverrideobjectGetValue(objectcomponent)
  116. {
  117. //Console.WriteLine("GetValue:"+component.GetHashCode());
  118. try
  119. {
  120. returnthis.info.GetValue(component,null);
  121. }
  122. catch
  123. {
  124. returnnull;
  125. }
  126. }
  127. publicoverridevoidResetValue(objectcomponent)
  128. {
  129. }
  130. publicoverridevoidSetValue(objectcomponent,objectvalue)
  131. {
  132. //Console.WriteLine("SetValue:"+component.GetHashCode());
  133. this.info.SetValue(component,value,null);
  134. }
  135. publicoverrideboolShouldSerializeValue(objectcomponent)
  136. {
  137. returnfalse;
  138. }
  139. //通过重载下面这个属性,可以将属性在PropertyGrid中的显示设置成中文
  140. publicoverridestringDisplayName
  141. {
  142. get
  143. {
  144. if(info!=null)
  145. {
  146. MyControlAttibuteuicontrolattibute=(MyControlAttibute)Attribute.GetCustomAttribute(info,typeof(MyControlAttibute));
  147. if(uicontrolattibute!=null)
  148. returnuicontrolattibute.PropertyName;
  149. else
  150. {
  151. returninfo.Name;
  152. }
  153. }
  154. else
  155. return"";
  156. }
  157. }
  158. }
  159. #endregion

修改后的Form界面如下:

Form中由于我仅仅是演示了TextBox所以我就是直接将创建TextBoxProperty对象的代码放在了Control_Click中:

//我这里仅仅做TextBox的属性演示,如果是其它的控件的话,那么你需要设计不同的ControlProperty(比如TextBoxPropertyComboBoxProperty

if (sender is TextBox)

{

this.propertyGrid1.SelectedObject = new TextBoxProperty((TextBox)sender);

}

else

{

this.propertyGrid1.SelectedObject = null;

}

对于实际的需要来说应该是根据Control的类型,通过工厂模式来创建ControlProperty

Form的整个代码如下,窗体如上图所示:

  1. //在Form中增加几个Button,分别命名为cmdArrow,cmdLabel,cmdTextBox,cmdComboBox,cmdGroupBox
  2. publicpartialclassForm1:Form
  3. {
  4. privateMouseHook_MouseHook;
  5. //我们将所有的已经与具体控件关联了的UISizeKnob缓存在这个HashTable中
  6. privateHashtable_HashUISizeKnob;
  7. //负责控件移动的类
  8. privateHashtable_HashUIMoveKnob;
  9. publicForm1()
  10. {
  11. InitializeComponent();
  12. this._MouseHook=newMouseHook(this);
  13. this._HashUISizeKnob=newHashtable();
  14. this._HashUIMoveKnob=newHashtable();
  15. //为了简洁明了,我们在ControlAdded中来设置具体控件和UISizeKnob的关联
  16. this.ControlAdded+=newControlEventHandler(Form1_ControlAdded);
  17. }
  18. voidForm1_ControlAdded(objectsender,ControlEventArgse)
  19. {
  20. if(!(e.ControlisUISizeDot))
  21. {
  22. this._HashUISizeKnob.Add(e.Control,newUISizeKnob(e.Control));
  23. this._HashUIMoveKnob.Add(e.Control,newUIMoveKnob(e.Control));
  24. //点击控件的时候,显示控件的选择
  25. e.Control.Click+=newEventHandler(Control_Click);
  26. }
  27. }
  28. voidControl_Click(objectsender,EventArgse)
  29. {
  30. //寿险清除已经选择的控件
  31. foreach(UISizeKnobknobinthis._HashUISizeKnob.Values)
  32. {
  33. knob.ShowUISizeDots(false);
  34. }
  35. //System.ComponentModel.Design.ISelectionService
  36. //System.Drawing.Design.IToolboxService
  37. try
  38. {
  39. ((UISizeKnob)this._HashUISizeKnob[sender]).ShowUISizeDots(true);
  40. //我这里仅仅做TextBox的属性演示,如果是其它的控件的话,那么你需要设计不同的ControlProperty(比如TextBoxProperty,ComboBoxProperty)
  41. if(senderisTextBox)
  42. {
  43. this.propertyGrid1.SelectedObject=newTextBoxProperty((TextBox)sender);
  44. }
  45. else
  46. {
  47. this.propertyGrid1.SelectedObject=null;
  48. }
  49. }
  50. catch{}
  51. }
  52. privatevoidcmdArrow_Click(objectsender,EventArgse)
  53. {
  54. SettingService.Instance.SelectedToolBoxControl=null;
  55. }
  56. privatevoidcmdLabel_Click(objectsender,EventArgse)
  57. {
  58. SettingService.Instance.SelectedToolBoxControl=newLabel();
  59. }
  60. privatevoidcmdTextBox_Click(objectsender,EventArgse)
  61. {
  62. SettingService.Instance.SelectedToolBoxControl=newTextBox();
  63. }
  64. privatevoidcmdComboBox_Click(objectsender,EventArgse)
  65. {
  66. SettingService.Instance.SelectedToolBoxControl=newComboBox();
  67. }
  68. privatevoidcmdGroupBox_Click(objectsender,EventArgse)
  69. {
  70. SettingService.Instance.SelectedToolBoxControl=newGroupBox();
  71. }
  72. }

好了,让

PropertyGrid显示中文属性的思路和代码都给了,希望能够给你点启发和帮助。

相关文章:

C#基础系列:开发自己的窗体设计器(总纲)

C#基础系列:开发自己的窗体设计器(在容器上拖动鼠标增加控件)

C#基础系列:开发自己的窗体设计器(实现控件的选择)

C#基础系列:开发自己的窗体设计器(实现控件的拖动)

分享到:
评论

相关推荐

    PropertyGrid 下拉式和弹出编辑框的实现

    在.NET框架中,`PropertyGrid`控件是一个强大的工具,用于在Windows Forms应用程序中显示和编辑对象的属性。它提供了一种用户友好的界面,使开发者可以轻松地创建具有属性浏览器功能的应用。在这个主题中,我们将...

    C# FromDesigner 自定义窗体设计器

    在.NET框架中,C#是一种常用的编程语言,用于构建各种应用程序,...在`WinFormDesigner`这个压缩包中,可能包含的就是一个用于演示或实践这些概念的示例项目,通过学习和分析,可以深入理解C#窗体设计器的定制方法。

    C#自制窗口设计器

    设计器通常会有一个宿主进程(Hosting Process),这个进程能够承载设计时环境,例如文件中的"Hosting"可能就是这样的一个进程,它负责加载并显示窗体设计器,同时提供设计时服务,如控件的添加、删除、布局调整等。...

    用c# 实现设计器 DesignSurface

    在.NET框架中,C#提供了一种强大的工具,允许开发者创建自定义的设计器,用于构建图形化设计界面,这就是DesignSurface。DesignSurface是System.Drawing.Design命名空间中的一个关键类,它为开发人员提供了在代码...

    PropertyGrid.rar

    它的主要优点在于简化了UI设计,开发者只需要提供一个对象实例,`PropertyGrid`就会自动地解析并显示其所有可读写的属性。 在C#中使用`PropertyGrid`,首先你需要在Windows Form上添加一个`PropertyGrid`控件,这...

    AE+C#实例开发教程

    综上所述,AE+C#实例开发教程不仅涵盖了基础的桌面GIS应用程序框架搭建过程,还包括了菜单功能、控件同步、状态栏信息显示、鹰眼功能、右键菜单、图层符号选择器以及属性数据表的查询显示等多个方面的知识点。...

    DataPropertyGrid控件,实现通过数据生成类,然后动态编译,然后放置到PropertyGrid中.zip

    在.NET框架中,`PropertyGrid`控件是一个强大的工具,用于显示和编辑对象的属性。这个控件在设计时提供了一个交互式的属性浏览器,通常用于配置对象或组件的设置。在给定的“DataPropertyGrid控件,实现通过数据生成...

    ArcGIS Engine + C# 实例开发教程.pdf

    - **属性数据表查询显示**:使用PropertyGrid控件显示和编辑地图对象的属性。 #### 8. 教程和资源 本教程由3SDN原创,提供了ArcGIS Engine和C#结合的实例开发教程,供GIS开发初学者使用。教程详细讲解了从框架建立...

    可显示和编辑数据的属性栏代码

    2. **属性网格初始化**:在窗体加载事件中,将要显示的对象实例赋值给`PropertyGrid`的`SelectedObject`属性。这会自动加载该对象的所有公共属性。 3. **自定义属性编辑器**:有时,内置的编辑器无法满足需求,这时...

    ArcGIS+Engine+C#实例开发教程

    - 属性面板使用PropertyGrid控件替换原来的DataGridView控件,更适合作为属性查询和设置的界面。 - 地图面板放置MapControl,提供地图浏览功能。 - 制版面板放置PageLayoutControl,用于地图的布局设计。 3. **...

    ArcGIS_Engine_C#实例开发教程

    - **问题修正**: 将“属性”选项卡中的 DataGridView 替换为 PropertyGrid 控件。 #### 二、菜单的添加及其实现 **1. 添加菜单** - **MenuStrip**: 在设计视图中键入菜单名称,例如“文件”、“编辑”等。 - **子...

    ArcGIS Engine+C#实例开发教程

    - **PropertyGrid**: 显示对象属性。 - **MapControl**: 主要的地图显示控件。 - **PageLayoutControl**: 布局控制,用于地图制图。 - **LicenseControl**: 用于授权验证。 按照以下步骤添加控件并设置属性: - 将...

    ArcGIS Engine+C#实例开发教程(PDF版)

    - **修改窗体名称**:在解决方案资源管理器中将默认的“Form1.cs”文件重命名为“3sdnMap.cs”,并在设计视图中修改窗体的`Text`属性为“3sdnMap”。 **知识点3:控件添加与布局** - **添加MenuStrip**:从工具箱...

    Winform实现类似Viso的简单的流程图

    在.NET Framework 2.0环境下,使用C#语言开发Windows Forms(Winform)应用程序,可以实现一个简单的流程图设计工具,其功能类似于知名的Visio软件。这个项目的主要目标是允许用户通过拖放操作来创建和编辑流程图。...

    AE 开发实例代码

    - 在“属性”选项卡中拖入`PropertyGrid`控件(而非`DataGridView`控件),设置其`Dock`属性为`Fill`。 4. **地图和布局控件**:在另一个`TabControl`控件中,创建两个选项卡——“地图”和“制版”,分别拖入`...

    用C#开发arcengine的例子

    - **PropertyGrid**:替换之前的DataGridView控件,在“属性”选项卡中拖拽PropertyGrid控件,并设置其“Dock”属性为“Fill”。 - **TabControl**:再次将TabControl控件拖拽到SplitContainer的右侧面板,并设置其...

    C# winForm框架

    - **属性网格(Property Grid)**:Visual Studio中的属性网格允许开发者实时调整控件属性,查看和修改控件的详细设置。 3. **事件驱动编程(Event-Driven Programming)** - **事件**:当用户与控件交互(如点击...

    ArcGIS_Engine开发实践

    - **DataGridView/PropertyGrid**:用于显示属性信息,放置在“属性”选项卡中。 - **MapControl/PageLayoutControl**:分别用于显示地图和页面布局。 完成控件的添加后,可以预览布局效果。 ##### 3. 控件绑定 ...

    ARCGIS ENGINE +C#编程实例教程

    (注意:应更改为PropertyGrid控件) - **添加地图和布局控件**:拖入TabControl控件到Panel2,设置Dock属性为Fill。将两个选项卡的Name和Text分别设置为:(tabPageMap、地图),(tabPageLayout,制版)。选择...

Global site tag (gtag.js) - Google Analytics