復(fù)合控件:將現(xiàn)有的各種控件組合起來,形成一個(gè)新的控件,將集中控件的功能集中起來。
擴(kuò)展控件:在現(xiàn)有控件的控件的基礎(chǔ)上派生出一個(gè)新的控件,為原有控件增加新的功能或者修改原有控件的控能。
自定義控件:直接從System.Windows.Forms.Control類派生出來。Control類提供控件所需要的所有基本功能,包括鍵盤和鼠標(biāo)的事件處理。自定義控件是最靈活最強(qiáng)大的方法,但是對(duì)開發(fā)者的要求也比較高,你必須為Control類的OnPaint事件寫代碼,你也可以重寫Control類的WndProc方法,處理更底層的Windows消息,所以你應(yīng)該了解GDI+和Windows API。
控件最大的特點(diǎn)就是具有設(shè)計(jì)時(shí)的UI界面了。同時(shí)控件的屬性設(shè)置也是很重要的一方面。
一、控件的Attribute
CategoryAttribute:指定當(dāng)屬性 (Property) 或事件顯示在一個(gè)設(shè)置為“按分類順序”模式的 System.Windows.Forms.PropertyGrid 控件中時(shí),用于給屬性或事件分組的類別的名稱。
如果為屬性設(shè)置了默認(rèn)值,那么修改了屬性的值以后,這個(gè)值在Property Explorer中會(huì)以粗體顯示。當(dāng)VS進(jìn)行控件的串行化時(shí),他會(huì)判斷哪些不是默認(rèn)值,只有不是默認(rèn)值的屬性才會(huì)被串行化,所以為屬性提供默認(rèn)值,可以大大減少串行化的屬性數(shù)目,提高效率。
簡(jiǎn)單屬性:
private String _displayText = "Hello World!";
[Browsable(true)]
[DefaultValue("Hello World")]
public String DisplayText
{
get
{
return _displayText;
}
set
{
_displayText = value;
Invalidate();
}
}
對(duì)于這些簡(jiǎn)單類型的屬性,只要使用DefaultValue,并在其構(gòu)造函數(shù)里傳入默認(rèn)值即可。
復(fù)雜屬性:
對(duì)于復(fù)雜的類型,比如Font,Color,你不能夠直接將這些類型的值傳遞給Attibute的構(gòu)造函數(shù)。相反你應(yīng)該提供Reset<PropertyName> 和ShouldSerialize<PropertyName>方法,比如有個(gè)BackgroundColor的屬性,那么應(yīng)該有下面兩個(gè)方法:ResetBackgroundColor(),ShouldSerializeBackgroundColor()。VS能夠根據(jù)方法的名稱來識(shí)別這種方法,比如Reset<PropertyName>方法把重置為默認(rèn)值,ShouldSerialize<PropertyName>方法檢查屬性是否是默認(rèn)值。過去我們把它稱之為魔術(shù)命名法,應(yīng)該說是一種不好的編程習(xí)慣,可是現(xiàn)在微軟依然使用這種機(jī)制。
當(dāng)然,默認(rèn)值設(shè)置了以后,還需要給我們的屬性設(shè)置默認(rèn)顯示的值。通過給屬性賦值實(shí)現(xiàn),比如:private String _displayText = "Hello World!";
DefaultValue設(shè)置的默認(rèn)值不會(huì)在屬性瀏覽器中顯示;
屬性私有字段設(shè)置的“值”,會(huì)在屬性瀏覽器中默認(rèn)顯示。
如果設(shè)置成兩個(gè)值相同,那么在屬性瀏覽器里就不是粗體,否則是粗體顯示。
大家要區(qū)別兩個(gè)關(guān)鍵詞: “默認(rèn)值”,“默認(rèn)顯示的值”
另外一種給復(fù)雜屬性設(shè)置默認(rèn)值的方式:
private Color _back = Color.Red;
[Browsable(true)]
[DefaultValue(typeof(Color), "Blue")]
public Color Back
{
get { return _back; }
set { _back = value; }
}
EditorAttribute:為屬性指定一個(gè)特殊的編輯器。
1.為了能夠?yàn)檫@個(gè)屬性編輯提供一個(gè)界面,我們需要實(shí)現(xiàn)自己的彈出式編輯對(duì)話框。如圖:
當(dāng)然,這僅僅是一個(gè)窗體,還不是什么屬性編輯器,每一個(gè)屬性的編輯器都是直接或者間接派生于UITypeEditor的,開發(fā)環(huán)境也不會(huì)直接調(diào)用我們的窗體,而是調(diào)用UITypeEditor的某些虛方法,所以我們還必須提供一個(gè)派生于UITypeEditor的累來與開發(fā)環(huán)境通信。
派生UITypeEditor以后,我們需要重寫兩個(gè)非那根發(fā),一個(gè)是GetEditStyle,另一個(gè)是EditValue。前者通知開發(fā)環(huán)境,屬性的編輯是一個(gè)模式對(duì)話框;后者是核心方法,通過上下文環(huán)境獲得正在編輯的控件的實(shí)例,并將實(shí)例的Scope屬性傳遞給屬性編輯對(duì)話框,顯示對(duì)話框供給用戶編輯屬性的值。
[Editor(typeof(ScopeEditor), typeof(UITypeEditor))]
2.提供下拉屬性編輯器
制作一個(gè)用戶控件,當(dāng)做屬性的編輯頁(yè)面:
和模態(tài)對(duì)話框編輯器一樣,開發(fā)環(huán)境并不會(huì)直接調(diào)用我們的編輯器控件,而是用過UITypeEditor類的派生來實(shí)現(xiàn)編輯器的調(diào)用,所以我們必須實(shí)現(xiàn)一個(gè)下拉式編輯器。
[Editor(typeof(ScopeDropDownEditor), typeof(UITypeEditor))]
LocalizableAttribute:指示一個(gè)屬性是否能被本地化,任何有這個(gè)Attribute的屬性將會(huì)被持久化到資源文件里。
DesignerSerializationVisibilityAttribute:指示一個(gè)屬性是否或者如何持久化到代碼里。
是一個(gè)枚舉值:一共有三種類型:Content,Hidden,Visible。Content指示代碼生成器為對(duì)象包含的內(nèi)容生成代碼,而不是為對(duì)象本身;Hidden指示代碼生成器不為對(duì)象生成代碼;visible指示代碼生成器為對(duì)象生成代碼。假如你的控件有一個(gè)集合屬性,又想在設(shè)計(jì)時(shí)自動(dòng)將集合屬性的內(nèi)容生成代碼,那么就使用這個(gè)Attribute,并將值設(shè)為DesignerSerializationVisibility.Content。
假設(shè)一個(gè)自定義控件中有Item的集合屬性:
在設(shè)計(jì)時(shí),可以添加,刪除
我們看添加完以后的代碼,會(huì)發(fā)現(xiàn),內(nèi)容被序列化到資源文件里了。
我們可以添加DesignerSerializationVisibilityAttribute
[DesignerSerializationVisibilityAttribute(
DesignerSerializationVisibility.Content)]
查看代碼:
我們可以發(fā)現(xiàn)被序列化到了源代碼里。
TypeConverterAttribute:為屬性指定一個(gè)類型轉(zhuǎn)換器,類型轉(zhuǎn)換器能將屬性的值轉(zhuǎn)化成其它的數(shù)據(jù)類型。如果屬性是自定義類型或者特殊類型,那么就得自己實(shí)現(xiàn)轉(zhuǎn)換器,并通過TypeConvertAttribute去實(shí)現(xiàn)了。類型轉(zhuǎn)換器都是從System.ComponentModel.TypeConverter派生出來的。
1.要實(shí)現(xiàn)一個(gè)類型轉(zhuǎn)換器,我們必須要重寫(override)四個(gè)方法:
CanConvertFrom()――根據(jù)類型參數(shù)進(jìn)行測(cè)試,判斷是否能從這個(gè)類型轉(zhuǎn)換成當(dāng)前類型,在本例中我們只提供轉(zhuǎn)換string和InstanceDescriptor類型的能力。
CanConvertTo()――根據(jù)類型參數(shù)進(jìn)行測(cè)試,判斷是否能從當(dāng)前類型轉(zhuǎn)換成指定的類型。
ConvertTo()――將參數(shù)value的值轉(zhuǎn)換為指定的類型。
ConvertFrom()――串換參數(shù)value,并返回但書類型的一個(gè)對(duì)象。
2.為了在屬性瀏覽器里能夠獨(dú)立的編輯子屬性,我們還要重寫兩個(gè)方法:GetPropertiesSupported()和GetProperties();
DefaultEventAttribute:為組件指定一個(gè)默認(rèn)的事件,當(dāng)用戶在form設(shè)計(jì)其中選擇一個(gè)控件的時(shí)候,在屬性瀏覽器中這個(gè)事件被選中。
聯(lián)系客服