.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,并在其构造函数里传入默认值即可。 复杂属性: 对于复杂的类型,比如Font,Color,你不能够直接将这些类型的值传递给Attibute的构造函数。相反你应该提供Reset<PropertyName> 和ShouldSerialize<PropertyName>方法,比如有个BackgroundColor的属性,那么应该有下面两个方法:ResetBackgroundColor(),ShouldSerializeBackgroundColor()。VS能够根据方法的名称来识别这种方法,比如Reset<PropertyName>方法把重置为默认值,ShouldSerialize<PropertyName>方法检查属性是否是默认值。过去我们把它称之为魔术命名法,应该说是一种不好的编程习惯,可是现在微软依然使用这种机制。 当然,默认值设置了以后,还需要给我们的属性设置默认显示的值。通过给属性赋值实现,比如: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; } }
1.为了能够为这个属性编辑提供一个界面,我们需要实现自己的弹出式编辑对话框。如图: 当然,这仅仅是一个窗体,还不是什么属性编辑器,每一个属性的编辑器都是直接或者间接派生于UITypeEditor的,开发环境也不会直接调用我们的窗体,而是调用UITypeEditor的某些虚方法,所以我们还必须提供一个派生于UITypeEditor的累来与开发环境通信。 派生UITypeEditor以后,我们需要重写两个非那根发,一个是GetEditStyle,另一个是EditValue。前者通知开发环境,属性的编辑是一个模式对话框;后者是核心方法,通过上下文环境获得正在编辑的控件的实例,并将实例的Scope属性传递给属性编辑对话框,显示对话框供给用户编辑属性的值。 [Editor(typeof(ScopeEditor), typeof(UITypeEditor))] 2.提供下拉属性编辑器 制作一个用户控件,当做属性的编辑页面: 和模态对话框编辑器一样,开发环境并不会直接调用我们的编辑器控件,而是用过UITypeEditor类的派生来实现编辑器的调用,所以我们必须实现一个下拉式编辑器。 [Editor(typeof(ScopeDropDownEditor), typeof(UITypeEditor))]
是一个枚举值:一共有三种类型:Content,Hidden,Visible。Content指示代码生成器为对象包含的内容生成代码,而不是为对象本身;Hidden指示代码生成器不为对象生成代码;visible指示代码生成器为对象生成代码。假如你的控件有一个集合属性,又想在设计时自动将集合属性的内容生成代码,那么就使用这个Attribute,并将值设为DesignerSerializationVisibility.Content。 假设一个自定义控件中有Item的集合属性: 在设计时,可以添加,删除 我们看添加完以后的代码,会发现,内容被序列化到资源文件里了。 我们可以添加DesignerSerializationVisibilityAttribute [DesignerSerializationVisibilityAttribute( DesignerSerializationVisibility.Content)] 查看代码: 我们可以发现被序列化到了源代码里。
1.要实现一个类型转换器,我们必须要重写(override)四个方法: 2.为了在属性浏览器里能够独立的编辑子属性,我们还要重写两个方法:GetPropertiesSupported()和GetProperties();
|
|