博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C#基础系列:开发自己的窗体设计器(PropertyGrid显示中文属性名)
阅读量:5014 次
发布时间:2019-06-12

本文共 11883 字,大约阅读时间需要 39 分钟。

既然是一个窗体设计器,那就应该能够设置控件的属性,设置属性最好的当然是PropertyGrid了,我们仅仅需要使用一个PropertyGrid.SelectedObject = Control就可以搞定,让PropertyGrid显示Control的所有属性。可是这里显示的属性名是英文的。对于我们开发人员来说这无可厚非,我们也乐于接受。并且让PropertyGrid显示中文属性名,这对于我们开发人员的使用来说显得多此一举。可是,对于我这种类型的一个应用工具,英文属性名对于很多客户来说可能就很难懂了。所以应该让PrpertyGrid能够显示中文属性名。

如图:

 

另外,对于这样的一个系统。并不是控件的所有属性都是用户希望的,可能用户希望看到的仅仅是控件高度、控件宽度、控件文本。。等等的属性,但是如果直接将一个控件属性全部显示给用户的话,估计对用户造成的干扰和困惑是很大的。如何解决这个问题呢?其实用户控件开发的时候,如果我们不希望此属性在PropertyGrid中显示,我们可以设置这个控件的Attribute,如:

[Browsable(false)]public int Width{    get { }    set { }}

通过使用BrowsableAttribute就可以设置将此属性对PropertyGrid隐藏。

 

你可能要问到了,对于控件来说,其中的很多属性都是直接继承来的,我们并没有办法控制是否对PropertyGrid隐藏啊?呵呵,对啊,这就是我下面要说的解决方法(当然此方法显得不是很灵活,但是对于这种类型的系统的确相当有用)。

在我的解决方式中,我不直接这样PropertyGrid.SelectedObject = Control,而是把这个Control替换成一个专门为此类型的Control设计的类对象上。比如我对TextBox设计了一个TextBoxProperty,这样我们使用的是PropertyGrid.SelectedObject = TextBoxProperty的一个对象。

下面就是TextBoxProperty的代码:

 

public class TextBoxProperty : PropertyBase{    private TextBox _Control;    public TextBoxProperty()    {    }    public TextBoxProperty(TextBox control)    {        this._Control = control;    }    [MyControlAttibute("文本", "获取或者设置控件文本", "")]    public string Text    {        get { return this._Control.Text; }        set        {            this._Control.Text = value;        }    }    [MyControlAttibute("宽度", "获取或者设置控件宽度", "")]    public int Width    {        get { return this._Control.Width; }        set        {            this._Control.Width = (int)value;        }    }    [MyControlAttibute("高度", "获取或者设置控件高度", "")]    public int Height    {        get { return this._Control.Height; }        set        {            this._Control.Height = (int)value;        }    }    [MyControlAttibute("上边距", "获取或者设置控件上边位置", "")]    public int Top    {        get { return this._Control.Top; }        set        {            this._Control.Top = value;        }    }    [MyControlAttibute("左边距", "获取或者设置控件左边位置", "")]    public int Left    {        get { return this._Control.Left; }        set        {            this._Control.Left = value;        }    }    [MyControlAttibute("背景色", "获取或者设置控件背景颜色", "")]    public Color BackColor    {        get { return this._Control.BackColor; }        set        {            this._Control.BackColor = value;        }    }    [MyControlAttibute("前景色", "获取或者设置控件的前景颜色", "")]    public Color ForeColor    {        get { return this._Control.ForeColor; }        set        {            this._Control.ForeColor = value;        }    }}

 

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

public class MyControlAttibute : Attribute{    private string _PropertyName;    private string _PropertyDescription;    private object _DefaultValue;    public MyControlAttibute(string Name, string Description, object DefalutValue)    {        this._PropertyName = Name;        this._PropertyDescription = Description;        this._DefaultValue = DefalutValue;    }    public MyControlAttibute(string Name, string Description)    {        this._PropertyName = Name;        this._PropertyDescription = Description;        this._DefaultValue = "";    }    public MyControlAttibute(string Name)    {        this._PropertyName = Name;        this._PropertyDescription = "";        this._DefaultValue = "";    }    public string PropertyName    {        get { return this._PropertyName; }    }    public string PropertyDescription    {        get { return this._PropertyDescription; }    }    public object DefaultValue    {        get { return this._DefaultValue; }    }}

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

public override string DisplayName{    get    {        if (info != null)        {            MyControlAttibute uicontrolattibute = (MyControlAttibute)Attribute.GetCustomAttribute(info, typeof(MyControlAttibute));            if (uicontrolattibute != null)                return uicontrolattibute.PropertyName;            else            {                return info.Name;            }        }        else            return "";    }}

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

public delegate void PropertyChanged(object Value);/// /// 主要是实现中文化属性显示/// public class PropertyBase : ICustomTypeDescriptor{    ///     /// 下面这段代码来源于:http://www.bluespace.cn/Html/Csdn/2_47/View_4702219.html    ///     /// 
#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") { //判断属性是否显示 BrowsableAttribute Browsable = (BrowsableAttribute)Attribute.GetCustomAttribute(p, typeof(BrowsableAttribute)); if (Browsable != null) { if (Browsable.Browsable == true || p.PropertyType.ToString() == "System.Drawing.Color") { PropertyStub psd = new PropertyStub(p, attributes); props.Add(psd); } } else { PropertyStub psd = new PropertyStub(p, attributes); props.Add(psd); } } } PropertyDescriptor[] propArray = (PropertyDescriptor[])props.ToArray(typeof(PropertyDescriptor)); return new PropertyDescriptorCollection(propArray); } object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) { return this; } #endregion}/// /// 下面这段代码来源于:http://www.bluespace.cn/Html/Csdn/2_47/View_4702219.html/// 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) { //Console.WriteLine("GetValue: " + component.GetHashCode()); try { return this.info.GetValue(component, null); } catch { return null; } } public override void ResetValue(object component) { } public override void SetValue(object component, object value) { //Console.WriteLine("SetValue: " + component.GetHashCode()); this.info.SetValue(component, value, null); } public override bool ShouldSerializeValue(object component) { return false; } //通过重载下面这个属性,可以将属性在PropertyGrid中的显示设置成中文 public override string DisplayName { get { if (info != null) { MyControlAttibute uicontrolattibute = (MyControlAttibute)Attribute.GetCustomAttribute(info, typeof(MyControlAttibute)); if (uicontrolattibute != null) return uicontrolattibute.PropertyName; else { return info.Name; } } else return ""; } }}

修改后的Form界面如下:

 

所以我就是直接将创建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的整个代码如下,窗体如上图所示:

//在Form中增加几个Button,分别命名为cmdArrow,cmdLabel,cmdTextBox,cmdComboBox,cmdGroupBoxpublic partial class Form1 : Form{    private MouseHook _MouseHook;    //我们将所有的已经与具体控件关联了的UISizeKnob缓存在这个HashTable中    private Hashtable _HashUISizeKnob;    //负责控件移动的类    private Hashtable _HashUIMoveKnob;    public Form1()    {        InitializeComponent();        this._MouseHook = new MouseHook(this);        this._HashUISizeKnob = new Hashtable();        this._HashUIMoveKnob = new Hashtable();        //为了简洁明了,我们在ControlAdded中来设置具体控件和UISizeKnob的关联        this.ControlAdded += new ControlEventHandler(Form1_ControlAdded);    }    void Form1_ControlAdded(object sender, ControlEventArgs e)    {        if (!(e.Control is UISizeDot))        {            this._HashUISizeKnob.Add(e.Control, new UISizeKnob(e.Control));            this._HashUIMoveKnob.Add(e.Control, new UIMoveKnob(e.Control));                        //点击控件的时候,显示控件的选择            e.Control.Click += new EventHandler(Control_Click);        }    }    void Control_Click(object sender, EventArgs e)    {        //寿险清除已经选择的控件        foreach (UISizeKnob knob in this._HashUISizeKnob.Values)        {            knob.ShowUISizeDots(false);        }        //System.ComponentModel.Design.ISelectionService        //System.Drawing.Design.IToolboxService        try         {            ((UISizeKnob)this._HashUISizeKnob[sender]).ShowUISizeDots(true);        //我这里仅仅做TextBox的属性演示,如果是其它的控件的话,那么你需要设计不同的ControlProperty(比如TextBoxProperty,ComboBoxProperty)        if (sender is TextBox)        {            this.propertyGrid1.SelectedObject = new TextBoxProperty((TextBox)sender);        }        else        {            this.propertyGrid1.SelectedObject = null;        }        }        catch { }    }        private void cmdArrow_Click(object sender, EventArgs e)    {        SettingService.Instance.SelectedToolBoxControl = null;    }    private void cmdLabel_Click(object sender, EventArgs e)    {        SettingService.Instance.SelectedToolBoxControl = new Label();    }    private void cmdTextBox_Click(object sender, EventArgs e)    {        SettingService.Instance.SelectedToolBoxControl = new TextBox();    }    private void cmdComboBox_Click(object sender, EventArgs e)    {        SettingService.Instance.SelectedToolBoxControl = new ComboBox();    }    private void cmdGroupBox_Click(object sender, EventArgs e)    {        SettingService.Instance.SelectedToolBoxControl = new GroupBox();    }}

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

 

相关文章:

 原文链接:

其他参考文献:

 

转载于:https://www.cnblogs.com/rainbow70626/p/6002188.html

你可能感兴趣的文章
Java读取并下载网络文件
查看>>
github上构建自己的个人网站
查看>>
在word中粘贴的图片为什么显示不完整
查看>>
SQL Server 数据库的鼠标操作
查看>>
net软件工程师求职简历
查看>>
总线置顶[置顶] Linux bus总线
查看>>
nullnullHandling the Results 处理结果
查看>>
SQL SERVER BOOK
查看>>
JS基础回顾,小练习(判断数组,以及函数)
查看>>
多任务——进程
查看>>
WCF:如何将net.tcp协议寄宿到IIS
查看>>
WebAPI HelpPage支持area
查看>>
Path元素
查看>>
php_soap扩展应用
查看>>
第二百三十一节,Bootstrap 介绍
查看>>
vi/vim 三种模式的操作
查看>>
JAVA面向对象三大特性总结
查看>>
guid
查看>>
Python中出现“TabError: inconsistent use of tabs and spaces in indentation”问题的解决
查看>>
ajax请求
查看>>