C#尽可能以最少的代码完成多层次的软件配置
使用C#尽可能以最少的代码完成多层次的软件配置(基于PropertyGrid控件)
1、前言
现在搜索PropertyGuid,发现的一些文档,特别是在百度文库中,都是互相抄,我发现最初的文档在这儿 http://msdn.microsoft.com/en-us/library/aa302326.aspx 。这里面也有一些错误,看的时候注意辨别一下。
2、目标:以最少的代码,实现在GUI中配置下列结构的对象。
namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private Database database = new Database(); } }
这个database对象就是待配置的对象,下面是Database类的结构:
public class Database { public string Name { get ; set ; } public string Password { get ; set ; } public string InitializeCommand { get ; set ; } public List<Table> Tables { get ; set ; } }
下面是Table类的结构:
public class Table { public string Name { get ; set ; } public List<Column> Columns { get ; set ; } public string Comment { get ; set ; } }
下面是Column类的结构:
public class Column { public string Name { get ; set ; } public SupportedType Type { get ; set ; } public string Comment { get ; set ; } public bool IsMainKey { get ; set ; } public bool NotNull { get ; set ; } public bool IsAutoIncrement { get ; set ; } public bool IsIndex { get ; set ; } }
下面是SupportedType的结构:
public enum SupportedType { Boolean, DateTime, Decimal, Double, Int64, Int32, Int16, SByte, Single, String, UInt64, UInt32, UInt16, Byte }
这里的例子用了大家都熟悉的数据库结构的模型,方便理解。
这里完成之后,向界面拖入Property控件,并把database字段赋给控件的SelectedObject属性,运行一下,得到以下效果:
点击...,得到以下效果:
点击“添加”,再点击...,得到以下效果:
可以注意到我并没有写多少代码,就完成的大部分的效果,和Visual Studio的属性窗口十分类似。但是,这个不美观,也有BUG,下面开始改善一下这些效果。
首先介绍一些在使用PropertyGrid控件时常用的Attribute(至于Attribute是什么,自行搜索之):
1)在属性框被点击后,光标自动跳到一个属性的框中:DefaultProperty,附着在类上,参数是属性的名称;
2)当值改变时,变成粗体的效果:DefaultValue,附着在属性上,参数是非粗体时的值;(注意这个不会决定默认值,这个决定粗体效果。)
3)对属性分类:Category,附着在属性上,参数是类别名称;
4)只读,不可编写,变灰色:ReadOnly,附着在属性上,参数是false或true,不加此Attribute的效果是此值为false的效果;
5)显示的名称,设置后不再显示为属性的名称:DisplayName,附着在属性上,参数是显示的名称;
6)描述信息,在描述框里显示:Description,附着在属性上,参数是描述信息;
7)是否显示:Browsable,附着在属性上,参数为false或true,不加此Attribute的效果是此值为true的效果。
以下是一些经验:
8)每个项都写成自动属性的形式;
9)在构造函数中对每一个值都尽可能赋值,这个也决定了默认值。没有这一步,可能造成设置后无法保存的BUG;
一般:string类型可以初始化为string.empty,bool类型不必初始化,List先判断是否为null,如果为null,初始化一下。
10)可以被正确识别的对象:各种值类型、String、数组、DateTime、TimeSpan、Point、Size、Font、Color、枚举类型、Image、Bitmap、Metafile、Icon、Cursor、List<T>。
下面是优化后的代码,都在这儿了:
public partial class Form1 : Form { public Form1() { InitializeComponent(); propertyGrid1.SelectedObject = database; } private readonly Database database = new Database(); }
[DefaultProperty( " Tables " )] public class Database { public Database() { Name = " NewDatabase " ; Password = string .Empty; InitializeCommand = string .Empty; if (Tables == null ) { Tables = new List<Table> (); } } [Category( " 属性 " ), DisplayName( " 数据库名称 " )] public string Name { get ; set ; } [Category( " 属性 " ), DisplayName( " 数据库密码 " )] public string Password { get ; set ; } [Category( " 属性 " ), DisplayName( " 初始化语句 " )] public string InitializeCommand { get ; set ; } [Category( " 数据表设置 " ), DisplayName( " 数据表集合 " )] public List<Table> Tables { get ; set ; } }
[DefaultProperty( " Columns " )] public class Table { public Table() { Name = " NewTable " ; Comment = string .Empty; if (Columns == null ) { Columns = new List<Column> (); } } [Category( " 属性 " ), DisplayName( " 数据表名称 " )] public string Name { get ; set ; } [Category( " 数据列设置 " ), DisplayName( " 数据列集合 " )] public List<Column> Columns { get ; set ; } [Category( " 属性 " ), DisplayName( " 备注 " )] public string Comment { get ; set ; } }
[DefaultProperty( " Name " )] public class Column { public Column() { Name = " NewColumn " ; Type = SupportedType.Int32; Comment = string .Empty; NotNull = true ; } [DisplayName( " 列名 " ), Category( " 属性 " )] public string Name { get ; set ; } [DisplayName( " 类型 " ), Category( " 属性 " )] public SupportedType Type { get ; set ; } [DisplayName( " 注释 " ), Category( " 属性 " )] public string Comment { get ; set ; } [DisplayName( " 是否是主键 " ), DefaultValue( false ), Category( " 属性 " )] public bool IsMainKey { get ; set ; } [DisplayName( " 是否非空 " ), DefaultValue( true ), Category( " 属性 " )] public bool NotNull { get ; set ; } [DisplayName( " 是否自动增长 " ), DefaultValue( false ), Category( " 属性 " )] public bool IsAutoIncrement { get ; set ; } [DisplayName( " 是否是索引 " ), DefaultValue( false ), Category( " 属性 " )] public bool IsIndex { get ; set ; } }
下面是优化后的效果:
3、遗留的问题
1)点击右上角的问号,没反应;
2)如果不是最顶层,就没有Description栏;
3)除了之前提到的一些类型,其它的类都不能自动使用上。
上述问题需要增加自定义的代码来解决,不符合本文“使用尽可能少的代码”的主题,相关的扩展心得会在之后的博文中表述出来。
分类: 工具分享
标签: C# , 配置 , 小工具 , NET , PropertyGrid
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于C#尽可能以最少的代码完成多层次的软件配置的详细内容...