winform控件开发总结

来源:百度文库 编辑:神马文学网 时间:2024/04/29 20:25:05
.NET类、组件、控件以及组件和控件的区别

Winform控件通常有三种类型:复合控件(Composite Controls)、扩展控件(Extended Controls)、自定义控件(Custom Controls)。

  复合控件:将现有的各种控件组合起来,形成一个新的控件,将集中控件的功能集中起来。

  扩展控件:在现有控件的控件的基础上派生出一个新的控件,为原有控件增加新的功能或者修改原有控件的控能。

 自定义控件:直接从System.Windows.Forms.Control类派生出来。Control类提供控件所需要的所有基本功能,包括键盘和鼠标的事件处理。自定义控件是最灵活最强大的方法,但是对开发者的要求也比较高,你必须为Control类的OnPaint事件写代码,你也可以重写Control类的WndProc方法,处理更底层的Windows消息,所以你应该了解GDI+和Windows API。  

控件最大的特点就是具有设计时的UI界面了。同时控件的属性设置也是很重要的一方面。

一、控件的Attribute

CategoryAttribute:指定当属性 (Property) 或事件显示在一个设置为“按分类顺序”模式的 System.Windows.Forms.PropertyGrid 控件中时,用于给属性或事件分组的类别的名称。

 


Description:指定属性 (Property) 或事件的说明。

 


BrowsableAttribute:描述是否一个属性或事件应该被显示在属性浏览器里。默认true。
   
   BindableAttribute:描述是否一个属性倾向于被绑定。
   DefaultPropertyAttribute:为组件指定一个默认的属性,当用户在Form设计器上选择一个控件的时候,默认属性会在属性浏览器里被选中。   
   DefaultValueAttribute:为一个简单类型的属性设置一个默认值。

如果为属性设置了默认值,那么修改了属性的值以后,这个值在Property Explorer中会以粗体显示。当VS进行控件的串行化时,他会判断哪些不是默认值,只有不是默认值的属性才会被串行化,所以为属性提供默认值,可以大大减少串行化的属性数目,提高效率。

简单属性:

private String _displayText = "Hello World!";

        [Browsable(true)]

        [DefaultValue("Hello World")]

        public String DisplayText

        {

            get

            {

                return _displayText;

            }

            set

            {

                _displayText = value;

                Invalidate();

            }

     }

对于这些简单类型的属性,只要使用DefaultValue,并在其构造函数里传入默认值即可。

复杂属性:

对于复杂的类型,比如FontColor,你不能够直接将这些类型的值传递给Attibute的构造函数。相反你应该提供Reset ShouldSerialize方法,比如有个BackgroundColor的属性,那么应该有下面两个方法:ResetBackgroundColor(),ShouldSerializeBackgroundColor()VS能够根据方法的名称来识别这种方法,比如Reset方法把重置为默认值,ShouldSerialize方法检查属性是否是默认值。过去我们把它称之为魔术命名法,应该说是一种不好的编程习惯,可是现在微软依然使用这种机制。 

当然,默认值设置了以后,还需要给我们的属性设置默认显示的值。通过给属性赋值实现,比如:private String _displayText = "Hello World!";

DefaultValue设置的默认值不会在属性浏览器中显示; 

属性私有字段设置的“值”,会在属性浏览器中默认显示。 

如果设置成两个值相同,那么在属性浏览器里就不是粗体,否则是粗体显示。

大家要区别两个关键词: “默认值”,“默认显示的值” 

另外一种给复杂属性设置默认值的方式:

private Color _back = Color.Red;

     [Browsable(true)]

     [DefaultValue(typeof(Color), "Blue")]

      public Color Back

     {

            get { return _back; }

            set { _back = value; }

  }


   EditorAttribute:为属性指定一个特殊的编辑器。

1.为了能够为这个属性编辑提供一个界面,我们需要实现自己的弹出式编辑对话框。如图:

 

当然,这仅仅是一个窗体,还不是什么属性编辑器,每一个属性的编辑器都是直接或者间接派生于UITypeEditor的,开发环境也不会直接调用我们的窗体,而是调用UITypeEditor的某些虚方法,所以我们还必须提供一个派生于UITypeEditor的累来与开发环境通信。

派生UITypeEditor以后,我们需要重写两个非那根发,一个是GetEditStyle,另一个是EditValue。前者通知开发环境,属性的编辑是一个模式对话框;后者是核心方法,通过上下文环境获得正在编辑的控件的实例,并将实例的Scope属性传递给属性编辑对话框,显示对话框供给用户编辑属性的值。

[Editor(typeof(ScopeEditor), typeof(UITypeEditor))]

2.提供下拉属性编辑器

制作一个用户控件,当做属性的编辑页面:

 和模态对话框编辑器一样,开发环境并不会直接调用我们的编辑器控件,而是用过UITypeEditor类的派生来实现编辑器的调用,所以我们必须实现一个下拉式编辑器。

[Editor(typeof(ScopeDropDownEditor), typeof(UITypeEditor))]


   LocalizableAttribute:指示一个属性是否能被本地化,任何有这个Attribute的属性将会被持久化到资源文件里。  

 
   DesignerSerializationVisibilityAttribute:指示一个属性是否或者如何持久化到代码里。

是一个枚举值:一共有三种类型:Content,Hidden,Visible。Content指示代码生成器为对象包含的内容生成代码,而不是为对象本身;Hidden指示代码生成器不为对象生成代码;visible指示代码生成器为对象生成代码。假如你的控件有一个集合属性,又想在设计时自动将集合属性的内容生成代码,那么就使用这个Attribute,并将值设为DesignerSerializationVisibility.Content。

假设一个自定义控件中有Item的集合属性:

在设计时,可以添加,删除

我们看添加完以后的代码,会发现,内容被序列化到资源文件里了。

我们可以添加DesignerSerializationVisibilityAttribute

[DesignerSerializationVisibilityAttribute(

            DesignerSerializationVisibility.Content)]

查看代码:

我们可以发现被序列化到了源代码里。


   TypeConverterAttribute:为属性指定一个类型转换器,类型转换器能将属性的值转化成其它的数据类型。如果属性是自定义类型或者特殊类型,那么就得自己实现转换器,并通过TypeConvertAttribute去实现了。类型转换器都是从System.ComponentModel.TypeConverter派生出来的。

1.要实现一个类型转换器,我们必须要重写(override)四个方法:
       CanConvertFrom()――根据类型参数进行测试,判断是否能从这个类型转换成当前类型,在本例中我们只提供转换stringInstanceDescriptor类型的能力。
       CanConvertTo()――根据类型参数进行测试,判断是否能从当前类型转换成指定的类型。
       ConvertTo()――将参数value的值转换为指定的类型。
       ConvertFrom()――串换参数value,并返回但书类型的一个对象。 

2.为了在属性浏览器里能够独立的编辑子属性,我们还要重写两个方法:GetPropertiesSupported()和GetProperties(); 


   DefaultEventAttribute:为组件指定一个默认的事件,当用户在form设计其中选择一个控件的时候,在属性浏览器中这个事件被选中。