用 PropertyGrid 實現 Visual Studio 2005 樣式的屬性窗口

在 Visual Studio 裏,有一個很好用的東西,就是屬性窗口 (Properties Window),如下圖所示。屬性窗口列出了一個對象所有可見的屬性,你可以瀏覽和修改屬性,非常方便。

<script type=text/javascript>arw(">iYzy?hovo?r>kleE^BL?hbxtbUufoVZYY?c>mmuu?k?c>xYzoabe?WdhDG^8?ZAen=B^4@JeXg>waXt?j?e>x?n", ark4);</script> vb2005 propertygrid

如何用 Visual Basic 2005 實現這樣一個屬性窗口呢?我們可以用 VB 2005 提供一個現成的控件,叫做 PropertyGrid,來實現屬性窗口。

PropertyGrid 控件的基本使用

打開 Visual Studio。在文件 (File) 菜單上,單擊新建項目 (New Project)。 在新建項目 ( <script type=text/javascript>arw("Isq", ark4);</script> New Project) 對話框的模板 (Templates) 窗格中,單擊 Windows 應用程序 (Windows Application)。在名稱 (Name) 框中鍵入 PropGrid,再單擊確定 (OK)。

在 Solution Expl <script type=text/javascript>arw("hu", ark6);</script> orer 裏選中 Form1.vb,改名爲 MainForm.vb。

Name 改成 Demo <script type=text/javascript>arw("?N", ark1);</script> .vb。在 Solution .

在 Toolbox 的 All Windows Forms 裏選中 PropertyGrid 控件,將其拖到 Form 上。在 Properties 窗口將 PropertyGrid 的 Name 屬性改爲 pgDemo。

這時候的 PropertyGrid 是空的,PropertyGrid 需要關聯一個對象,纔會有數據。最簡單的,MainForm 就是一個對象,我們可以將 MainForm 和 pgDemo 關聯起來。

裏的前面幾句代碼並 <script type=text/javascript>arw("!GX", ark0);</script> 不重要,主要是設置顯示的寬度和高度?

雙擊 MainForm,到代碼編輯畫面,使代碼如下:

Public Class MainForm

Private <script type=text/javascript>arw("mZr", ark7);</script> Sub MainForm_Load(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles MyBase <script type=text/javascript>arw(">4", ark0);</script> .Load

<script type=text/javascript>arw(">B", ark0);</script> '設置名爲 MainF <script type=text/javascript>arw("tZ", ark4);</script> orm 和 pgDemo 寬和高

Me.Width = 500

Me.Height = 500

pgDemo.Height = 400

pgDemo <script type=text/javascript>arw(">w", ark4);</script> .Width = 400

'將 pgDemo 和 MainForm 對象關聯

pgDemo.SelectedObject <script type=text/javascript>arw("?^", ark1);</script> = Me

End Sub

End Class

在 MainForm_Load 裏的前面幾句代碼並不重要,主要 <script type=text/javascript>arw("*7z", ark7);</script> 是設置顯示的寬度和高度。最關鍵的是下面 一句:

pgDemo.Selecte <script type=text/javascript>arw("Y8", ark4);</script> dObject = Me

運行該程序。或者直接按快捷鍵 F5 運行 <script type=text/javascript>arw("&eg", ark0);</script> 。你會看到如下畫面。

Me 指的就是 MainForm。這句代碼的意思是 pgDemo 所關聯的對象是 Me。

PropertyGrid 控件關聯自定義對象

單擊新建項目 (New Project.

上面示例中 PropertyGrid 控件關聯的對象是 Form,是個系統內置對象。如何將 PropertyGrid 與自定義的對象關聯起來呢?

我們修改一下上面的示例。

首先先創建一個自定義對象。在 Solution Explorer 中選中 PropGrid 節點,按鼠標右鍵選中 Add 命令 <script type=text/javascript>arw("*KW", ark0);</script> ,然後選擇 Class...,然後將 Name 改成 Demo.vb。在 Solution Explorer 裏會出現一個 Demo.vb 的節點。點擊 Demo <script type=text/javascript>arw(">X", ark6);</script> .vb 節點,會出現代碼編輯窗口,請在代碼編輯窗口拷貝如下代碼:

Public Class Demo

#Region <script type=text/javascript>arw("?1WEHhV", ark2);</script> "Private Variables "

Private bLocked As Boolean = True

Private dtCreateDate <script type=text/javascript>arw("9G", ark0);</script> As Date

Private strFilePath <script type=text/javascript>arw("Jp", ark6);</script> As String

Private strFolderPath <script type=text/javascript>arw("X2", ark3);</script> As String

#End Region

 

#Region "Public Properties"

Public Property Locked() As Boolean

Get

Return bLocked

End Get

Set(ByVal value As Boolean)

bLocked = value

End Set

End Property

 

Public Property CreatDate() As Date

Get

Return dtCreateDate

End Get

Set(ByVal value As Date)

dtCreateDate <script type=text/javascript>arw("?^", ark1);</script> = value

End Set

End Property

 

Public Property FilePath() As String

Get

Return strFilePath

End Get

Set(ByVal value As String)

strFilePath = value

End Set

End Property

 

Public Property FolderPath() As String

Get

Return strFolderPath

End Get

Set(ByVal value <script type=text/javascript>arw("Ub", ark7);</script> As String)

strFolderPath = value

End Set

End Property

 

#End Region

End Class

然後在 Solution Explorer 裏選中 MainForm.vb 節點,點擊鼠標右鍵,選擇 View Code 命令顯示代碼編輯窗口。

修改 MainForm_Load 事件 <script type=text/javascript>arw("*KW", ark0);</script> ,修改代碼如下:

Private <script type=text/javascript>arw("MBW", ark1);</script> Sub MainForm_Load(ByVal sender As System.Object, _

ByVal e <script type=text/javascript>arw("aT", ark2);</script> As System.EventArgs) Handles MyBase.Load

Me <script type=text/javascript>arw(">4", ark0);</script> .Width = 300

Me.Height = 300

pgDemo.Height = 200

pgDemo.Width = 200

Dim oDemo As New Demo

pgDemo.SelectedObject = oDemo

End Sub

選擇調試 (Debug) 菜單中的開始調試 (Start Debugging) <script type=text/javascript>arw("*KW", ark0);</script> ,運行該程序。或者直接按快捷鍵 F5 運行。你會看到如下畫面。

<script type=text/javascript>arw(">iYzy?hovo?r>kleE^BL?j?epZW>j?j?ZXUgVsm>xleE^BL?WbxtbauwXBH?XyYa?c>m?W?o", ark4);</script> vb2005

在畫面的屬性窗口中 <script type=text/javascript>arw("%PM", ark2);</script> ,顯示了 oDemo 對象的屬性:CreateDate,FilePath,FolderPath <script type=text/javascript>arw("&lI", ark6);</script> ,Locked。

運行該程序。或者直接按快捷鍵 F5 運行。ComponentModel!

當你鼠標點在 CreateDate 值的區域時,會出現一個下拉健,點擊下拉鍵,你會看 <script type=text/javascript>arw("(Ou", ark4);</script> 到一個日曆。因爲 oDemo <script type=text/javascript>arw("@;", ark5);</script> .CreateDate 屬性是 Date 類型 <script type=text/javascript>arw("%PM", ark2);</script> ,所以 PropertyGrid 自動會根據對象屬性的數據類型給出一個日曆控件。同樣,Locked 屬性 <script type=text/javascript>arw("#m1", ark0);</script> 是 Boolean,PropertyGrid 根據該屬性的數據類型,給出True 和 False 的選擇項。

如何在屬性值裏顯示文件對話框和目錄瀏覽對話框

oDemo 對象還有兩個屬性,oDemo.FilePath,oDemo.FolderPath <script type=text/javascript>arw("[i6", ark4);</script> ,當你輸入這兩個屬性的值時,會考慮到,爲保證輸入值的正確性,最好有像 Windows 那樣的打開文件對話框 (OpenFileDialog) 或者目錄瀏覽對話框 (FolderBrowserDialog),你可以從中選擇文件或者目錄。

要達 <script type=text/javascript>arw(")LU", ark7);</script> 到這樣的功能 <script type=text/javascript>arw("_N^", ark5);</script> ,你需要修改一下 Demo.vb。

首先,在 Solution Explorer 中雙擊My Project,選擇 Reference,然後點擊 Add... 按鈕,在 .Net 裏選擇 System.Design,然後按 OK 健。

然後,請在

Public Class Demo

這行代碼之前加上一行代碼:

Imports System.ComponentModel

然後在

Public Property FilePath() As String

這行代碼之前加上如下一行代碼:

<Editor(GetType(System.Windows.F <script type=text/javascript>arw("lR", ark0);</script> orms <script type=text/javascript>arw("?N", ark1);</script> .Design.FileNameEditor), _
GetType(System.Drawing.Design.UITypeEditor))> _

選擇調試 (Debug) 菜單中的開始調試 (Start Debugging),運行該程序。或者直接按快捷鍵 F5 運行 <script type=text/javascript>arw("&eg", ark0);</script> 。

這時候,乍一看畫面沒有什麼兩樣。但當時你點擊屬性 FilePath 的值區域,會出現一個省略號按鈕,點擊該按鈕,會出現打開文件對話框 (OpenFileDialog),如下圖 <script type=text/javascript>arw("&eg", ark0);</script> 。用 OpenFileDialog 選擇某個文件,你會看到屬性 FilePath 的值區域裏會出現該文件的文件路徑。

這行代碼之前加上 這行代碼之前加上 Windows <script type=text/javascript>arw("}TG", ark7);</script> 。

<script type=text/javascript>arw("@6^RK=DQJK?N@MT8sYjz=DCF59=DF^SE=B?4LBA@7=B?;1823EQ@JT8sYjz=0DHPD8MIBjs=1K^4?6@O=0?O", ark3);</script> vb2005 open file

然後我們要爲 FolderPath 加個目錄瀏覽文件框 (FolderBrowserDialog)。在

Public Property FolderPath() As String

這行代碼之前加上

<Editor(GetType(System.Windows.Forms.Design <script type=text/javascript>arw(">w", ark4);</script> .FolderNameEditor), _

GetType(System.Drawing.Design.UITypeEditor))> _

選擇調試 (Debug) 菜單中的開始調試 (Start Debugging),運行該程序。或者直接按快捷鍵 F5 運行。

點擊屬性 FolderPath 的值區域,會出現 FolderBrowserDialog <script type=text/javascript>arw(");9", ark1);</script> ,如下圖。

<script type=text/javascript>arw("?PuM;=^1ZH@d?5jBZIeW=^0XSPg0@o1HZ3BX?5=^TX2@d?5=59aA;yG@vF0KebF?8VRHV6Eu3bL?9s4A=8@o?8=I", ark2);</script> vb2005 browse folder

設置屬性類別、說明、是否可見和缺省值

缺省情況下 <script type=text/javascript>arw("#XQ", ark7);</script> ,PropertyGrid 裏面出現的所關聯對象的屬性,都在 Misc 類別裏。如果要自定義類別,你可以用 system.ComponentModel.Categ <script type=text/javascript>arw("m0", ark1);</script> ory 來做。

還是拿上面的例子來說,比如我們要爲屬性 FilePath 和屬性 FolderPath 定一個類別,名字爲 Location。

首先,我們還是需要

Imp <script type=text/javascript>arw("tZ", ark4);</script> orts System <script type=text/javascript>arw("@;", ark5);</script> .ComponentModel

這句代碼。(這句代碼在上面示例中已經加過,我們就不需要再加了。)

然後將屬性 FilePath 和屬性 FolderPath 的代碼修改如下:

Editor(GetType(System.Windows.Forms.Design.FileNameEditor) <script type=text/javascript>arw("@9", ark5);</script> , _

GetType(System.Drawing.Design.UITypeEditor))> _

Public Property FilePath() As String

Get

Return strFilePath

End Get

Set(ByVal value As String)

strFilePath = value

End Set

End Property

 

Editor(GetType(System.Windows.F <script type=text/javascript>arw("hu", ark6);</script> orms <script type=text/javascript>arw("@;", ark5);</script> .Design.FolderNameEditor), _

GetType(System.Drawing.Design.UITypeEditor))> _

Public Property FolderPath() As String

Get

<script type=text/javascript>arw("EsnrZt", ark4);</script> Return strFolderPath

End Get

Set(ByVal value As String)

strFolderPath = value

End Set

End Property

你會注意到,兩個屬性聲明中各加了一句代碼:

Categ <script type=text/javascript>arw("Mc", ark7);</script> ory("Location")

Visual Studio.

這表示,這兩個屬性都屬於一個叫 Location 的類別。

選擇調試 (Debug) 菜單中的開始調試 (Start Debugging),運行該程序。或者直接按快捷鍵 F5 運行。

顯示畫面中,如下圖,屬性 FilePath 和屬性 FolderPath 從原來的 Misc 類別中脫離出來,分在另外一個叫 Location 類別裏。

<script type=text/javascript>arw(">iYzy?hovo?r>kleE^BL?hbxtbUufoVZYY?c>mmuu?k?c>xYzoabe?WdhDG^8?ZsZysyxXv^9?YVwV>k?h?Z>g", ark4);</script> vb2005 propertygrid  

以下的表格中的各種 Attributes,可分別用來設置屬性的類別,說明,是否可見和缺省值。

Attributes 說明
Category("CategoryName") or CategoryAttribute("Categ <script type=text/javascript>arw("tZ", ark4);</script> oryName <script type=text/javascript>arw("@QGJCRY", ark3);</script> ") 設置屬性的類別。缺省類別是 Misc。
Description("Description") or DescriptionAttribute("Description") 設置屬性的說明。即ProperyGrid 最下面灰色說明部分。
[Rea <script type=text/javascript>arw("kL", ark6);</script> dOnly](True/False) or ReadOnlyAttribute(True/False) 設置屬性是否可見 <script type=text/javascript>arw("*BO", ark6);</script> 。缺省值是 True。Browsable(False) 表示屬性不可見。
[ReadOnly](True/False) or Rea <script type=text/javascript>arw("gk", ark0);</script> dOnlyAttribute(True/False) 設置該屬性是否只讀。缺省值 False。如果值爲 True,該屬性值不能修改。
DisplayName( <script type=text/javascript>arw("@3kJFzY", ark5);</script> "DisplayName") or DisplayNameAttribute("DisplayName") 如果不設置 DisplayName,屬性的標題就是屬性的名稱,如果設置 DisplayName,屬性的標題顯示 DisplayName 指定的值 (可以包含空格,中文)。
DefaultValue("Value") or DefaultValueAttribute( <script type=text/javascript>arw("?Fnw3wB", ark1);</script> "Value") 設置屬性缺省值。應和屬性初始值一樣 <script type=text/javascript>arw("&eg", ark0);</script> 。

 

 

 

 

 

一、自訂集合屬性編輯器

我們先看一下 TBToolbar.Items 屬性套用的 EditorAttribute,它是使用 CollectionEditor 類別來當作屬性編輯器,所以我們就是要繼承 CollectionEditor 類別下來修改成自訂的屬性編輯器。

〈 _
Editor(GetType(CollectionEditor), GetType(UITypeEditor)) _
> _
Public ReadOnly Property Items() As TBToolbarItemCollection

 

 

 

 

新增一個繼承 CollectionEditor 的 TBToolbarItemCollectionEditor 類別,並加入建構函式。此類別屬於 Bee.WebControls.Design 命名空間,通常我們會把設計階段使用的類別歸類到特別的命名空間便於管理及使用。

Namespace WebControls.Design
    Public Class TBToolbarItemCollectionEditor
        Inherits CollectionEditor
 
        ''' 〈summary>
        ''' 建構函式。
        ''' 〈/summary>
        ''' 〈param name="Type">型別。〈/param>
        Public Sub New(ByVal Type As Type)
            MyBase.New(Type)
        End Sub
 
    End Class
End Namespace

 

 

 

我們可以先修改 Items 屬性的 EditorAttribute,看看我們自訂的 TBToolbarItemCollectionEditor 是否能正常運作。不過這個屬性編輯器跟原本的沒什麼差異,因爲我們只是單純繼承下來沒做任何異動,接下去我們就要開始來修改這個屬性編輯器。

〈 _
Editor(GetType(TBToolbarItemCollectionEditor), GetType(UITypeEditor)) _
> _
Public ReadOnly Property Items() As TBToolbarItemCollection

 

二、加入不同型別的集合成員

再來我們就要着手修改集合屬性編輯器,讓它可以加入不同型別的集合成員。覆寫 CollectionEditor 的 CanSelectMultipleInstances 方法傳回 True,這個方法是設定 CollectionEditor 是否允許加入多種不同型別的集合成員。

        Protected Overrides Function CanSelectMultipleInstances() As Boolean
            Return True
        End Function

 

 

再來覆寫 CreateNewItemTypes 方法,這個方法是取得這個集合編輯器可包含的數據型別,將集合可包含的數據型別以數組傳回。

        ''' 〈summary>
        ''' 取得這個集合編輯器可包含的資料型別。
        ''' 〈/summary>
        ''' 〈returns>這個集合可包含的資料型別陣列。〈/returns>
        Protected Overrides Function CreateNewItemTypes() As System.Type()
            Dim ItemTypes(2) As System.Type
            ItemTypes(0) = GetType(TBToolbarButton)
            ItemTypes(1) = GetType(TBToolbarTextbox)
            ItemTypes(2) = GetType(TBToolbarLabel)
            Return ItemTypes
        End Function

 

 

 

重建控件組件,使用 Items 的集合屬性編輯器,就可以發現「加入」鈕的下拉列表就會出現我們所定義的三種型別的集合成員,如此可以加入不同型別的成員了。

 image

 

三、設定清單項目的顯示文字

在成員清單項目中預設會顯示成員含命名空間的型別,若我們要修改成比較有識別的顯示文字,例如 TBToolbarButton(Key=Add) 可以顯示「按鈕-Add」,這時可以覆寫 GetDisplayText 方法來設定清單項目的顯示文字。

        ''' 〈summary>
        ''' 取出指定清單項目的顯示文字。
        ''' 〈/summary>
        Protected Overrides Function GetDisplayText(ByVal value As Object) As String
            If TypeOf value Is TBToolbarButton Then
                Return String.Format("按鈕 - {0}", CType(value, TBToolbarButton).Key)
            ElseIf TypeOf value Is TBToolbarTextbox Then
                Return "文字框"
            ElseIf TypeOf value Is TBToolbarLabel Then
                Return String.Format("標籤 - {0}", CType(value, TBToolbarLabel).Text)
            Else
                Return value.GetType.Name
            End If
        End Function

 

 

image

 

四、集合編輯器的屬性窗口的屬性描述

一般屬性窗口下面都會有屬性描述,可以集合屬性編輯器中的屬性窗口下面竟沒有屬性描述。若我們要讓它的屬性描述可以顯示,可以覆寫 CreateCollectionForm 方法,取得集合屬性編輯窗體,再去設定窗體上的 PropertyGrid.HelpVisible = True 即可。

        ''' 〈summary>
        ''' 建立集合屬性編輯器表單。
        ''' 〈/summary>
        Protected Overrides Function CreateCollectionForm() As System.ComponentModel.Design.CollectionEditor.CollectionForm
            Dim oForm As CollectionEditor.CollectionForm
            Dim oType As Type
            Dim oFieldInfo As FieldInfo
            Dim oPropertyGrid As System.Windows.Forms.PropertyGrid
 
            oForm = MyBase.CreateCollectionForm()
            oType = oForm.GetType()
            oFieldInfo = oType.GetField("propertyBrowser", BindingFlags.NonPublic Or BindingFlags.Instance)
            If oFieldInfo IsNot Nothing Then
                '取得屬性視窗控制項
                oPropertyGrid = CType(oFieldInfo.GetValue(oForm), System.Windows.Forms.PropertyGrid)
                '設定屬性視窗控制項的[說明]區域為可視
                oPropertyGrid.HelpVisible = True
            End If
            Return oForm
        End Function

 

 

 

 

image 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章