第 3 步:實現屬性和事件 要實現 Status 屬性,首先要為可能的屬性值創建枚舉。將以下幾行插入以 Inherits 開始的行下面:
Public Enum TrafficLightStatus statusRed = 1 statusYellow = 2 statusGreen = 3 End Enum
此枚舉是公開的,也就是說使用該控件的窗體可以訪問它。
在這些行下面添加以下三行:
Dim mStatus As TrafficLightStatus = TrafficLightStatus.statusGreen Dim msngBorderWidth As Single = 1.0! Public Event StatusChanged(ByVal NewStatus As TrafficLightStatus)
前兩行中的兩個變量可用于存儲 Status 和 BorderWidth 屬性的屬性值,還為這些屬性設置了默認值。保存 BorderWidth 的變量必須為 Single 類型,因為它是繪制邊框所用的圖形語句需要的類型。默認值中的驚嘆號也表明它是 Single 類型。此集合中的最后一行聲明了 StatusChanged 事件。
現在,我們為 BorderWidth 屬性編寫代碼。在標記為 Windows Form Designer Generated Code(Windows 窗體設計器生成的代碼)的代碼區域下插入以下行:
<DefaultValue(1.0!), _ Description("紅綠燈周圍邊框的寬度")> _ Public Property BorderWidth() As Single Get Return msngBorderWidth End Get Set(ByVal Value As Single) If msngBorderWidth <> Value Then msngBorderWidth = Value Me.Invalidate() End If End Set End Property
前兩行包括使該屬性更好地使用 IDE 的屬性。DefaultValue 特性允許在 Properties(屬性)窗口中將屬性值重置為默認值(操作步驟稍后介紹)。Description 特性提供選中該屬性時在 Properties(屬性)窗口底部顯示的文本。
DefaultValue 特性還有一個技巧。如果將 TrafficLight 控件放到窗體上,并保留 BorderWidth 屬性的默認值,那么窗體設計器將不生成設置屬性值的代碼行。這使它與其他 Windows 窗體控件沒有什么區別。如果您查看典型控件(如 TextBox)的設計器生成的代碼,您會發現只包括設置為非默認值的屬性的代碼行。我們賦予 TrafficLight 控件同樣的能力。
Property Get 簡單明了。Property Set 子句包括可視控件屬性中常見的邏輯。設置屬性時,重要的是在新屬性值更改控件的外觀時要能夠重新繪制控件。因此,Set 子句負責確定傳遞的新值是否與屬性中現有的值不相同。如果相同,則不執行操作。如果不同,則接受新值,然后訪問控件的 Invalidate 方法。此方法表明,控件的可視區域已過期,控件需要重新繪制。
Status 屬性的處理有些不同,因為它是枚舉值。DefaultValue 特性沒有為枚舉屬性提供自動重置能力。在這種情況下,DefaultValue 也無法告訴設計器何時停止設置屬性值的代碼。因此,Status 屬性的實現中不需要 DefaultValue 特性。下面是 Status 屬性的代碼:
<Description("紅綠燈的狀態(顏色)")> _ Public Property Status() As TrafficLightStatus Get Status = mStatus End Get Set(ByVal Value As TrafficLightStatus) If mStatus <> Value Then mStatus = Value RaiseEvent StatusChanged(mStatus) Me.Invalidate() End If End Set End Property
看起來與 BorderWidth 屬性的實現類似,只有一點不同:當 Status 屬性發生改變時,除了強制重新繪制控件外,還會觸發 StatusChanged 事件。
要在 Properties(屬性)窗口中處理屬性的自動重置,我們需要使用一種特殊的方法。由于我們的屬性命名為 Status,因此必須將重置方法命名為 ResetStatus。重置方法只是恢復屬性的默認值。以下是其代碼:
Public Sub ResetStatus() Me.Status = TrafficLightStatus.statusGreen End Sub
為了提示設計器何時需要包括一行代碼以便設置 Status 屬性,我們需要包括一個名為 ShouldSerializeStatus 的方法。當屬性需要一行代碼時,此方法返回布爾值 True,否則,則返回 False。以下是其代碼:
Public Function ShouldSerializeStatus() As Boolean If mStatus = TrafficLightStatus.statusGreen Then Return False Else Return True End If End Function
|