c#——Winform PropertyGrid使用

来源:互联网 发布:彩票号码组合软件 编辑:程序博客网 时间:2024/06/05 05:36

最近被迫调到某部,协助一个配置工具的开发。

做winform的开发,这些控件相关的知识还是在学校上课的时候学到的。工作之后,没有接触相关的开发。

使用的是SCSF框架,控件使用winform自带控件。但是界面功能要求比较复杂。

一开始上手,还是有些困难,同时也有些排斥。但是一想自己这么痛苦,其实就是自己的基础不扎实。慢慢的放松了对自己的要求。

任何事情,做就做好。不得不做的时候,就努力做到最好的样子,争取从中学到一些知识,而不仅仅是完成任务。

不多说,调整心态,积累一些开发过程的经验。

这里学到大量的重载 和 扩展,以前一般只用其本身的功能。慢慢适应,如何扩展得到自己想要的效果。

要求使用propertyGrid

  1. 动态显示不同的属性列表
  2. 属性列表顺序已有定义
  3. 属性名称显示中文。
简单说一下解决方案:

  • 第一点使用对象动态绑定到控件即可
  • 第二点需要设置控件属性中的PropertySort为NoSort,这样就会使用绑定对象的属性顺序,即达到自定义属性列表的顺序
  • 第三点这个需要重写Attribute方法,否则无法实现,显示中文。因为默认显示属性字段的名称
下面讲一下具体的实现过程

首先需要写一个新的Attribute,重载一些方法,使得能够改变属性展示名称的来源。
代码如下:
using System;namespace Jurassic.AdapterConfig.FileEntityRetrieveModule.Services.Model{    public class MyControlAttibute : Attribute    {        private readonly string _categoryName;        private readonly string _propertyName;        private readonly string _propertyDescription;        private readonly object _defaultValue;        public MyControlAttibute(string categoryName, string name, string description, object defalutValue)        {            _categoryName = categoryName;            this._propertyName = name;            this._propertyDescription = description;            this._defaultValue = defalutValue;        }        public MyControlAttibute(string categoryName, string name, string description)        {            this._propertyName = name;            this._propertyDescription = description;            _categoryName = categoryName;            this._defaultValue = "";        }        public MyControlAttibute(string categoryName, string name)        {            this._propertyName = name;            _categoryName = categoryName;            this._propertyDescription = "";            this._defaultValue = "";        }        public MyControlAttibute(string name)        {            this._propertyName = name;            _categoryName = "";            this._propertyDescription = "";            this._defaultValue = "";        }        public string CategoryName        {            get { return this._categoryName; }        }        public string PropertyName        {            get { return this._propertyName; }        }        public string PropertyDescription        {            get { return this._propertyDescription; }        }        public object DefaultValue        {            get { return this._defaultValue; }        }    }}

写一个PropertyBase继承自System.ComponentModel的ICustomTypeDescriptor。提供为对象提供动态自定义类型信息的接口
所有绑定的对象类都需要继承PropertyBase类
代码如下

    public class PropertyBase : ICustomTypeDescriptor    {        /// <summary>        /// 下面这段代码来源于:http://www.bluespace.cn/Html/Csdn/2_47/View_4702219.html        /// </summary>        /// <returns></returns>        #region ICustomTypeDescriptor 显式接口定义        AttributeCollection ICustomTypeDescriptor.GetAttributes()        {            return TypeDescriptor.GetAttributes(this, true);        }        string ICustomTypeDescriptor.GetClassName()        {            return TypeDescriptor.GetClassName(this, true);        }        string ICustomTypeDescriptor.GetComponentName()        {            return TypeDescriptor.GetComponentName(this, true);        }        TypeConverter ICustomTypeDescriptor.GetConverter()        {            return TypeDescriptor.GetConverter(this, true);        }        EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()        {            return TypeDescriptor.GetDefaultEvent(this, true);        }        PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()        {            return null;        }        object ICustomTypeDescriptor.GetEditor(Type editorBaseType)        {            return TypeDescriptor.GetEditor(this, editorBaseType, true);        }        EventDescriptorCollection ICustomTypeDescriptor.GetEvents()        {            return TypeDescriptor.GetEvents(this, true);        }        EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)        {            return TypeDescriptor.GetEvents(this, attributes, true);        }        PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()        {            return ((ICustomTypeDescriptor)this).GetProperties(new Attribute[0]);        }        PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)        {            ArrayList props = new ArrayList();            Type thisType = this.GetType();            PropertyInfo[] pis = thisType.GetProperties();            foreach (PropertyInfo p in pis)            {                if (p.DeclaringType == thisType || p.PropertyType.ToString() == "System.Drawing.Color")                {                    //判断属性是否显示                    var browsable = (BrowsableAttribute)Attribute.GetCustomAttribute(p, typeof(BrowsableAttribute));                    if (browsable != null)                    {                        if (browsable.Browsable == true || p.PropertyType.ToString() == "System.Drawing.Color")                        {                            var psd = new PropertyStub(p, attributes);                            props.Add(psd);                        }                    }                    else                    {                        var psd = new PropertyStub(p, attributes);                        props.Add(psd);                    }                }            }            var propArray = (PropertyDescriptor[])props.ToArray(typeof(PropertyDescriptor));            return new PropertyDescriptorCollection(propArray);        }        object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)        {            return this;        }        #endregion    }


上面的类中需要调用PropertyStub,继承自System.ComponentModel的PropertyDescriptor
代码如下
 public class PropertyStub : PropertyDescriptor    {        PropertyInfo info;        public PropertyStub(PropertyInfo propertyInfo, Attribute[] attrs)            : base(propertyInfo.Name, attrs)        {            this.info = propertyInfo;        }        public override Type ComponentType        {            get { return this.info.ReflectedType; }        }        public override bool IsReadOnly        {            get { return this.info.CanWrite == false; }        }        public override Type PropertyType        {            get { return this.info.PropertyType; }        }        public override bool CanResetValue(object component)        {            return false;        }        public override object GetValue(object component)        {            try            {                return this.info.GetValue(component, null);            }            catch            {                return null;            }        }        public override void ResetValue(object component)        {        }        public override void SetValue(object component, object value)        {            this.info.SetValue(component, value, null);        }        public override bool ShouldSerializeValue(object component)        {            return false;        }        //通过重载下面这个属性,可以将属性在PropertyGrid中的显示设置成中文        public override string DisplayName        {            get            {                if (info != null)                {                    var uicontrolattibute = (MyControlAttibute)Attribute.GetCustomAttribute(info, typeof(MyControlAttibute));                    if (uicontrolattibute != null)                        return uicontrolattibute.PropertyName;                    return info.Name;                }                return "";            }        }        public override string Category        {            get            {                if (info != null)                {                    var uicontrolattibute = (MyControlAttibute)Attribute.GetCustomAttribute(info, typeof(MyControlAttibute));                    if (uicontrolattibute != null)                        return uicontrolattibute.CategoryName;                    return info.Name;                }                return "";            }        }        public override string Description        {            get            {                if (info != null)                {                    var uicontrolattibute = (MyControlAttibute)Attribute.GetCustomAttribute(info, typeof(MyControlAttibute));                    if (uicontrolattibute != null)                        return uicontrolattibute.PropertyDescription;                    return info.Name;                }                return "";            }        }    }

以上三步就做好的基础的工作,然后就编写绑定的基础类

using System.ComponentModel;namespace Jurassic.AdapterConfig.FileEntityRetrieveModule.Services.Model{    /// <summary>    /// 实体抓取逻辑 DB 配置信息    /// </summary>    public class DbRetrieveConfig : PropertyBase    {        private string _connectionStr;        private string _tableName;        private string _fieldName;        private string _sql;        [ MyControlAttibute("实体抓取逻辑(DB Blob)","数据库连接", "设置数据库连接字符串")]        public string ConnectionStr        {            get { return _connectionStr; }            set            {                if (!string.IsNullOrEmpty(value))                {                    _connectionStr = value.Trim();                }            }        }        [ MyControlAttibute("实体抓取逻辑(DB Blob)", "表名称", "获取或设置数据库表名称")]        public string TableName        {            get { return _tableName; }            set            {                if (!string.IsNullOrEmpty(value))                {                    _tableName = value.Trim();                }            }        }        [MyControlAttibute("实体抓取逻辑(DB Blob)", "表字段", "获取或设置数据库表字段")]        public string FieldName        {            get { return _fieldName; }            set            {                if (!string.IsNullOrEmpty(value))                {                    _fieldName = value.Trim();                }            }        }        [ MyControlAttibute("实体抓取逻辑(DB Blob)", "SQL", "获取或设置执行的SQL语句")]        public string Sql        {            get { return _sql; }            set            {                if (!string.IsNullOrEmpty(value))                {                    _sql = value.Trim();                }            }        }    }}
using System.ComponentModel;namespace Jurassic.AdapterConfig.FileEntityRetrieveModule.Services.Model{    /// <summary>    /// 实体抓取逻辑 FTP 配置信息    /// </summary>    public class FtpRetriveConfig : PropertyBase    {        private string _iP;        private string _userName;        private string _pwd;        private int _port;        private string _filePath;        [MyControlAttibute("实体抓取逻辑(FTP)", "服务器", "获取或设置服务器IP地址")]        public string IP        {            get { return _iP; }            set            {                if (!string.IsNullOrEmpty(value))                {                    _iP = value.Trim();                }            }        }        [MyControlAttibute("实体抓取逻辑(FTP)", "端口", "获取或设置服务器端口")]        public int Port        {            get { return _port; }            set { _port = value; }        }        [MyControlAttibute("实体抓取逻辑(FTP)", "用户名", "获取或设置用户名")]        public string UserName        {            get { return _userName; }            set            {                if (!string.IsNullOrEmpty(value))                {                    _userName = value.Trim();                }            }        }        [MyControlAttibute("实体抓取逻辑(FTP)", "密码", "获取或设置密码")]        public string Pwd        {            get { return _pwd; }            set            {                if (!string.IsNullOrEmpty(value))                {                    _pwd = value.Trim();                }            }        }        [MyControlAttibute("实体抓取逻辑(FTP)", "文件路径", "获取或设置实体存放的文件路径")]        public string FilePath        {            get { return _filePath; }            set            {                if (!string.IsNullOrEmpty(value))                {                    _filePath = value.Trim();                }            }        }    }}

以上定义了两个实体类,并且都继承PropertyBase。而且使用自定义的MyAttribute属性。
一切准备就绪,接下来就是数据绑定喽!
真不容易哦

在view中调用
     public void SetPropertyGridData(string type, PropertyBase connection)        {            this.tlscboStoragType.Text = type;            this.propgrdEntityRetrieve.SelectedObject = connection;        }

将两种实体类传过来就可以动态展示喽

最后一步,设置属性PropertySort为NoSort



这样,我们最后看一下展示的效果哦
1.


2.



1 0