逐步解說:使用 ASP.NET 使用者控制項建立可重複使用的項目
更新:2007 年 11 月
ASP.NET 使用者控制項可讓您將多個伺服器控制項的功能封裝在一個單元內。使用者控制項由一個或多個 ASP.NET 伺服器控制項 (Button 控制項、TextBox 控制項等),以及控制項執行您要完成之功能所需的所有程式碼組成。使用者控制項還可包括將使用者控制項的功能顯示給容器 (通常是 ASP.NET Web 網頁) 的自訂屬性或方法。
在這個逐步解說中,您會建立做為選擇器控制項的 ASP.NET 使用者控制項。選擇器控制項具有兩個清單,其中一個清單 (來源) 包含一組選擇。使用者可以選擇 [SourceList] 清單中的項目,然後將項目加入 [TargetList] 清單。
這個逐步解說具有三個部分,如下所示:
在第一部分中,您會建立基本使用者控制項,加入控制項和程式碼。
在第二部分中,您會建立新的 ASP.NET Web 網頁 (裝載頁面),然後將使用者控制項加入 ASP.NET Web 網頁。
在第三部分中,您會將自訂屬性和方法加入使用者控制項,以便與來自裝載頁面的控制項互動。
本逐步解說將說明的工作包括下列項目:
建立使用者控制項並將 ASP.NET 伺服器控制項加入使用者控制項。
在使用者控制項中建立屬性和方法。
將使用者控制項加入裝載頁面。
將程式碼加入裝載頁面以處理使用者控制項。
必要條件
若要完成這個逐步解說,您必須進行下列步驟:
Microsoft Visual Web Developer Web 開發工具。
Microsoft .NET Framework。
本逐步解說假設您已對 Visual Web Developer 中的工作具有一般了解。如需簡介,請參閱逐步解說:在 Visual Web Developer 中建立基本 Web 網頁。
建立網站
如果您已在 Visual Web Developer 中建立了網站 (例如,藉由完成逐步解說:在 Visual Web Developer 中建立基本 Web 網頁中的步驟),則可使用該網站,並繼續進行下一節的步驟。否則,依照下列這些步驟建立新的網站和 Web 網頁。
若要建立檔案系統網站
開啟 Visual Web Developer。
在 [檔案] 功能表上指向 [新增],然後按一下 [網站]。
[新網站] 對話方塊隨即出現。
請在 [Visual Studio 安裝的範本] 下方,按一下 [ASP.NET 網站]。
在最右邊的 [位置] 方塊中,輸入您想要用來保存網站頁面的資料夾名稱。
例如,輸入資料夾名稱 C:\WebSites。
在 [語言] 清單中,按一下您想要操作的程式語言。
按一下 [確定]。
Visual Web Developer 會建立資料夾和命名為 Default.aspx 的新頁面。
建立使用者控制項
建立使用者控制項與建立 ASP.NET Web 網頁類似。實際上,使用者控制項是 ASP.NET Web 網頁的子集,可包括您置於 ASP.NET Web 網頁上的大部分項目型別。
建立使用者控制項
在 [方案總管] 中,以滑鼠右鍵按一下網站名稱,然後再按一下 [加入新項目]。
在 [加入新項目 <Path>] 對話方塊中的 [Visual Studio 安裝的範本] 下,按一下 [Web 使用者控制項]。
在 [名稱] 方塊中,輸入 ListPicker。
使用者控制項檔將具有 .ascx 副檔名,該副檔名會自動加入 [ListPicker]。
在 [語言] 清單中,按一下您想要操作的程式語言。
按一下 [加入]。
新的控制項便會建立,並在設計工具中開啟。控制項的標記與網頁類似,但重要一點區別在於:網頁頂端沒有 @ Page 指示詞。而是具有 @ Control 指示詞,ASP.NET 將其用於識別做為使用者控制項的檔案。
將伺服器控制項加入使用者控制項
在逐步解說的這個部分中,您將加入組成使用者控制項之使用者介面的控制項。
若要加入伺服器控制項
切換到 [設計] 檢視 (如果您正在使用程式碼後置 (Code-Behind) 的頁面,請切換至 ListPicker.ascx 控制項,然後再切換至 [設計] 檢視)。
按一下 [表格] 功能表上的 [插入表格]。
使用 [插入表格] 對話方塊,建立具有一列三行的表格,然後按一下 [確定]。
您所建立的表格是用於包含控制項的版面配置表格。
在表格的左欄中,輸入可用,然後按 ENTER 鍵建立新行。
在右欄中,輸入已選取,然後按 ENTER 鍵建立新行。
從 [工具箱] 的 [標準] 群組中,將下列控制項拖曳至表格,並根據指示設定其屬性。
控制項
屬性
將 [ListBox] 拖曳至左欄,並將其置於 [可用] 下。
高度:200px
ID:SourceList
寬度:200px
將 [Button] 拖曳到中間欄。
ID:AddAll
文字:>>
將 [Button] 拖曳到中間欄。
ID:AddOne
文字:(空格鍵)>(空格鍵)
將 [Button] 拖曳到中間欄。
ID:移除
文字:(空格鍵)X(空格鍵)
將 [ListBox] 拖曳至右欄,並將其置於 [已選取] 下。
高度:200px
ID:TargetList
寬度:200px
可以使用 ImageButton 控制項取代 Button 控制項,以便在按一下滑鼠之後顯示影像。然而,在此逐步解說中,可以使用模擬經常用於表示 [全部加入]、[加入] 和 [移除] 之圖形類型的文字,分別是兩個右角括弧 (>>)、一個右角括弧 (>) 和 X。
如果需要,可根據偏好設定調整表格欄的寬度和高度。
按一下 [SourceList] 清單,然後在 [屬性] 中針對 Items 屬性按省略 (…) 按鈕。
[ListItem 集合編輯器] 對話方塊便會出現。
按三次 [加入] 以加入三個項目
針對第一、第二和第三個項目,在 [ListItem 屬性] 下,分別將 [Text] 設為 A、B 和 C。
您正在建立暫時測試資料。在這個逐步解說稍後的「將自訂屬性和方法加入使用者控制項」中,您將移除測試資料,並加入程式碼,以動態載入 [SourceList] 清單。
加入要處理使用者選取項目的程式碼
使用者將使用表格中間欄中的按鈕選取項目。因此,控制項的大部分程式碼都位於 Click 事件的處理常式中。
若要加入要處理使用者選取項目的程式碼
在 [設計] 檢視中,按兩下 [>>] ([AddAll]) 按鈕,為 Click 事件建立事件處理常式,然後加入下列反白顯示的程式碼。
Protected Sub AddAll_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles AddAll.Click TargetList.SelectedIndex = -1 Dim li As ListItem For Each li In SourceList.Items AddItem(li) Next End Sub
protected void AddAll_Click(object sender, EventArgs e) { TargetList.SelectedIndex = -1; foreach(ListItem li in SourceList.Items) { AddItem(li); } }
該程式碼會在 [SourceList] 清單的清單項目中執行迴圈 (Loop)。對於每個項目,它會呼叫 AddItem 方法,並為其傳遞目前的項目。在本程序的稍後部分中,您將撰寫 AddItem 方法的程式碼。
切換至 [設計] 檢視,按兩下 [>] ([AddOne]) 按鈕,為 Click 事件建立事件處理常式,然後加入下列反白顯示的程式碼:
Protected Sub AddOne_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles AddOne.Click If SourceList.SelectedIndex >= 0 Then AddItem(SourceList.SelectedItem) End If End Sub
protected void AddOne_Click(object sender, EventArgs e) { if(SourceList.SelectedIndex >= 0) { AddItem(SourceList.SelectedItem); } }
此程式碼會首先檢查 [SourceList] 清單中是否有選取項目。如果有,則程式碼 (您將在本程序稍後撰寫該程式碼) 會呼叫 AddItem 方法,向其傳遞 [SourceList] 清單中目前選取的項目。
切換至 [設計] 檢視,按兩下 [X] ([移除]) 按鈕,為 Click 事件建立事件處理常式,然後加入下列反白顯示的程式碼:
Protected Sub Remove_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles Remove.Click If TargetList.SelectedIndex >= 0 Then TargetList.Items.RemoveAt(TargetList.SelectedIndex) TargetList.SelectedIndex = -1 End If End Sub
protected void Remove_Click(object sender, EventArgs e) { if (TargetList.SelectedIndex >= 0) { TargetList.Items.RemoveAt(TargetList.SelectedIndex); TargetList.SelectedIndex = -1; } }
該程式碼首先檢查 [TargetList] 清單是否包含選取項目。如果有選取項目,則程式碼會從清單移除已選取的項目,並移除該選取項目。
加入下列 AddItem 方法:
Protected Sub AddItem(ByVal li As ListItem) TargetList.SelectedIndex = -1 TargetList.Items.Add(li) End Sub
protected void AddItem(ListItem li) { TargetList.SelectedIndex = -1; TargetList.Items.Add(li); }
此程式碼會無條件地將項目加入 [TargetList] 清單。在這個逐步解說稍後的「將自訂屬性和方法加入使用者控制項」中,您將藉由加入判斷是否重複的選項,以改善此程式碼。
您無法直接測試使用者控制項,因為它必須在網頁中裝載 (Host)。在下一節中,您將建立可在其中使用控制項的 ASP.NET Web 網頁。
使用使用者控制項
與任何控制項一樣,使用者控制項必須在網頁中裝載。在逐步解說的這個部分中,您將建立控制項的裝載頁面,然後將使用者控制項加入網頁。
若要建立裝載頁面
在 [方案總管] 中,以滑鼠右鍵按一下網站名稱,然後再按一下 [加入新項目]。
請在 [Visual Studio 安裝的範本] 下方,選取 [Web Form]。
在 [名稱] 方塊中,輸入 HostUserControl。
在 [語言] 清單中,選擇您想要操作的語言,然後按一下 [加入]。
新網頁隨即出現在設計工具中。
若要將使用者控制項加入網頁
切換至 [設計] 檢視。
從 [方案總管] 中,將使用者控制項檔 (ListPicker.ascx) 拖曳至網頁。
注意事項: 將 ListPicker.ascx 拖曳至網頁時,請確定您位於 [設計] 檢視。
控制項隨即出現在設計工具中。
切換至原始碼檢視。
將使用者控制項置於網頁上會在網頁中建立兩個新項目:
位於頁面頂端的是新的 @ Register 指示詞,它看起來與下列內容相同:
<%@ Register Src="ListPicker.ascx" TagName="ListPicker" TagPrefix="uc1" %>
@ Register 指示詞是必要的,因為使用者控制項是外部元件。該指示詞中的值會提供 ASP.NET 在編譯和執行網頁時尋找控制項所需的資訊。TagPrefix 和 TagName 屬性 (Attribute) 一起指定使用者控制項在網頁上的宣告方式。Src 屬性會指定檔案,如果必要,還指定原始程式檔 (Source File) 所在的路徑。
第二個新項目是使用者控制項的項目,它看起來與下列內容相同:
<uc1:ListPicker id="ListPicker1" Runat="server" />
使用者控制項的項目與一般 ASP.NET 伺服器控制項的項目類似。不同之處在於,使用者控制項具有不同的標記 (Tag) 前置詞 (uc1) 和唯一的標記名稱 (ListPicker)。儘管這些值是由 @ Register指示詞在您將使用者控制項置於網頁上時自動建立的,您仍然可以將任何標記前置詞和標記名稱用於使用者控制項,只要網頁尚未使用這些值即可。
測試使用者控制項
現在您可以測試使用者控制項的預備版本。
若要測試使用者控制項
按 CTRL+F5 執行頁面。
網頁隨即出現在瀏覽器中,且您可以看到組成使用者控制項的兩個清單和三個按鈕。
按一下 [>>] (全部加入) 按鈕。
會複製 [SourceList] 清單的所有值至 [TargetList] 清單。
依序按一下 [TargetList] 清單中的每個項目,再按一下 [X] ([移除]) 按鈕,直到移除所有項目為止。
在 [SourceList] 清單中選取單一值,然後按一下 [>] (AddOne) 按鈕。
會複製該單一值至 [TargetList] 清單。
選擇性地進行更多的控制項實驗,直到您確定其運作方式符合您的預期為止。
完成後,關閉瀏覽器。
將自訂屬性和方法加入使用者控制項
使用者控制項現在可以運作,但還不像一般用途的控制項那樣有效。使用者控制項的更可行版本可讓您執行下列操作:
指定在 [SourceList] 清單中動態顯示的項目清單。
獲得使用者在 [TargetList] 清單中選取的項目清單。
選擇性地指定在 [TargetList] 清單中是否允許重複值。
向使用者提供快速清除 [TargetList] 清單中所有項目的方式。
執行這些工作需要裝載頁面可以與使用者控制項通訊,以共用值 (設定和讀取屬性) 和發出命令 (呼叫方法)。在逐步解說的這個部分中,您將變更使用者控制項,並將一些成員 (屬性和方法) 加入其中。
您會將兩個屬性加入使用者控制項。第一個屬性會擷取 [TargetList] 清單中的項目清單。第二個屬性可讓您指定 [TargetList] 清單是否接受重複值。在本節稍後的內容中,您將加入可讓您填入 (Populate) [SourceList] 清單的方法。
若要加入要定義自訂屬性程式碼
針對 [ListPicker] 控制項,開啟或切換至程式碼檔。
使用下列程式碼建立 SelectedItems 屬性:
Public ReadOnly Property SelectedItems() As ListItemCollection Get Return TargetList.Items End Get End Property
public ListItemCollection SelectedItems { get { return TargetList.Items ; } }
SelectedItems 屬性會擷取 [TargetList] 清單中的值。它可能是唯讀的,因為您將無需以程式的方式設定 [TargetList] 清單中的值。
使用下列程式碼建立 AllowDuplicates 屬性:
Public Property AllowDuplicates() As Boolean Get Return CType(ViewState("allowDuplicates"), Boolean) End Get Set(ByVal value As Boolean) ViewState("allowDuplicates") = value End Set End Property
public Boolean AllowDuplicates { get { return (Boolean)ViewState["allowDuplicates"]; } set { ViewState["allowDuplicates"] = value; } }
AllowDuplicates 屬性是一個讀取/寫入屬性。AllowDuplicates 屬性的值必須明確地以「檢視」狀態儲存,才能來回設定 (SelectedItems 屬性不需要明確地以「檢視」狀態儲存,原因在於 [TargetList] 清單會以「檢視」狀態儲存值)。
現在您已定義屬性。然而,您仍必須修改使用者控制項中的現存程式碼,才能利用 AllowDuplicates 屬性設定。
若要修改現存程式碼以使用 AllowDuplicates 屬性
尋找您在這個逐步解說稍早之「加入要處理使用者選取項目的程式碼」中撰寫的 AddItem 方法,並使用下列反白顯示的程式碼取代內容:
Protected Sub AddItem(ByVal li As ListItem) TargetList.Selectedindex = -1 If Me.AllowDuplicates = True Then TargetList.Items.Add(li) Else If TargetList.Items.FindByText(li.Text) Is Nothing Then TargetList.Items.Add(li) End If End If End Sub
protected void AddItem(ListItem li) { TargetList.SelectedIndex = -1; if (this.AllowDuplicates == true) { TargetList.Items.Add(li); } else { if (TargetList.Items.FindByText(li.Text) == null) { TargetList.Items.Add(li); } } }
該程式碼會執行與之前相同的功能 (將項目加入 [TargetList] 清單),但該程式碼現在會檢查以判斷 AllowDuplicate 屬性是否設為 true。如果 AllowDuplicate 屬性設為 true,則程式碼首先尋找具有與建議新項目相同值的現有項目,然後加入新項目,但只在找不到現有項目時才可行。
因為您將使用屬性設定 [SourceList] 清單的內容,所以可以移除在這個逐步解說稍早之「將伺服器控制項加入使用者控制項」中輸入的測試資料。
若要移除 SourceList 清單的測試資料
切換至 [設計] 檢視。
按一下 [SourceList] 控制項,然後在 [屬性] 中針對 [項目] 按省略 (…) 按鈕。
[ListItem 集合編輯器] 隨即出現。
按一下 [移除] 按鈕,以移除每個範例項目,然後按一下 [確定]。
將方法加入使用者控制項
您還可於程式碼在裝載頁面中呼叫方法時,加入方法以執行使用者控制項中的工作。為了說明此內容,您將在這個逐步解說中加入兩個方法。可呼叫第一個方法,以將項目加入 [SourceList] 清單。第二個方法會清除 [TargetList] 清單的內容。
若要加入要清除 TargetList 清單的方法
使用下列程式碼加入 AddSourceItem 方法:
Public Sub AddSourceItem(ByVal sourceItem As String) SourceList.Items.Add(sourceItem) End Sub
public void AddSourceItem(String sourceItem) { SourceList.Items.Add(sourceItem); }
使用下列程式碼加入 ClearAll 方法:
Public Sub ClearAll() SourceList.Items.Clear() TargetList.Items.Clear() End Sub
public void ClearAll() { SourceList.Items.Clear(); TargetList.Items.Clear(); }
在 [檔案] 功能表上,按一下 [全部儲存],以儲存您對使用者控制項所做的變更。
測試使用者控制項屬性和方法
這個逐步解說的最終工作是增強裝載頁面,以便與使用者控制項共用值。您可以宣告方式設定某些使用者控制項的屬性 (您不能在此逐步解說中使用程式碼,直接設定 [SourceList] 清單,但是可以程式設計的方式設定)。在這個過程中,您會將 AllowDuplicates 屬性設為預設值 true。
若要以宣告方式設定使用者控制項屬性
切換至或開啟 HostUserControl.aspx 網頁。
在 [原始碼] 檢視中,藉由使用與下列相似的語法,以宣告方式設定 [AllowDuplicates]:
<uc1:ListPicker id="ListPicker1" Runat="server" AllowDuplicates="true" />
請注意,您會取得 [AllowDuplicates] 的 Microsoft IntelliSense 功能。
以程式的方式使用使用者控制項
您還可以程式的方式使用使用者控制項,設定和擷取屬性並呼叫方法。為了說明如何以程式的方式使用使用者控制項,您會將部分控制項加入裝載頁面。
若要以程式的方式使用使用者控制項
切換至 [設計] 檢視。
從 [工具箱] 的 [標準] 群組中,將下列控制項拖曳至裝載頁面上的表格,並根據指示設定屬性。
控制項
屬性
TextBox
ID:NewItem
文字:(空白)
Button
ID:AddItem
文字:Add Item
Button
ID:LoadFiles
文字:檔案清單
Button
ID:ClearSelection
文字:全部清除
CheckBox
AutoPostBack:True
Checked:True
ID:AllowDuplicates
文字:允許重複
Button
ID:ShowSelection
文字:顯示選取項目
Label
ID:Selection
文字:(空白)
在 [設計] 檢視中,按兩下 [AllowDuplicates],為 CheckedChanged 事件建立事件處理常式,然後加入下列反白顯示的程式碼:
Protected Sub AllowDuplicates_CheckedChanged( _ ByVal sender As Object, _ ByVal e As EventArgs) Handles AllowDuplicates.CheckedChanged ListPicker1.AllowDuplicates = AllowDuplicates.Checked End Sub
protected void AllowDuplicates_CheckedChanged(Object sender, EventArgs e) { ListPicker1.AllowDuplicates = AllowDuplicates.Checked; }
切換至 [設計] 檢視,按兩下 [AddItem],為 Click 事件建立事件處理常式,然後加入下列反白顯示的程式碼:
Protected Sub AddItem_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles AddItem.Click Dim sourceItem As String = Server.HtmlEncode(NewItem.Text) ListPicker1.AddSourceItem(sourceItem) End Sub
protected void AddItem_Click(object sender, EventArgs e) { ListPicker1.AddSourceItem(Server.HtmlEncode(NewItem.Text)); }
該程式碼會在程式碼中建立 ListItemCollection 集合,並在其中填入資料範例。然後,該程式碼會將 SourceItems 屬性設為該集合。
切換至 [設計] 檢視,按兩下 [LoadFiles],為 Click 事件建立事件處理常式,然後加入下列反白顯示的程式碼:
Protected Sub LoadFiles_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles LoadFiles.Click Dim path As String = Server.MapPath(Request.ApplicationPath) Dim files() As String = System.IO.Directory.GetFiles(path) Dim filename As String For Each filename in Files ListPicker1.AddSourceItem(filename) Next End Sub
protected void LoadFiles_Click(object sender, EventArgs e) { String path = Server.MapPath(Request.ApplicationPath); String[] files = System.IO.Directory.GetFiles(path); foreach(String filename in files) { ListPicker1.AddSourceItem(filename); } }
此程式碼與 [AddItem] 的程式碼類似,不同之處在於此程式碼會在網站根目錄中加入檔案清單。
切換至 [設計] 檢視,按兩下 [ShowSelection],為 Click 事件建立事件處理常式,然後加入下列反白顯示的程式碼:
Protected Sub ShowSelection_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles ShowSelection.Click Dim lItem As ListItem Dim selectedItemsString As String = "" For Each lItem in ListPicker1.SelectedItems selectedItemsString &= "<br>" & lItem.Text Next Selection.Text = selectedItemsString End Sub
protected void ShowSelection_Click(object sender, EventArgs e) { String selectedItemsString = ""; foreach(ListItem lItem in ListPicker1.SelectedItems) { selectedItemsString += "<br>" + lItem.Text; } Selection.Text = selectedItemsString; }
此程式碼會擷取型別是 ListItemCollection 物件的物件,並讀取集合中的每個項目,然後在 [Selection] 中顯示結果。
切換至 [設計] 檢視,按兩下 [ClearSelection],為 Click 事件建立事件處理常式,然後加入下列反白顯示的程式碼:
Protected Sub ClearSelection_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles ClearSelection.Click ListPicker1.ClearAll() End Sub
protected void ClearSelection_Click(object sender, EventArgs e) { ListPicker1.ClearAll(); }
此程式碼會叫用 (Invoke) 使用者控制項的 ClearAll 方法,以從 [TargetList] 中移除所有項目。
測試已完成的使用者控制項
現在您可以測試已完成的使用者控制項。
若要測試使用者控制項
按 CTRL+F5 執行頁面。
在文字方塊中輸入數值,然後按一下 [加入項目] 按鈕。
重複步驟 2 數次,直到使用者控制項中具有選取項目為止。
使用按鈕從 [SourceList] 清單中選取一個或多個來源項目,然後將其加入 [TargetList] 清單。
按一下 [顯示選取項目]。
[TargetList] 清單項目隨即顯示在 [Selection] 中。
按一下 [全部清除]。
按一下 [檔案清單]。
[SourceList] 清單現在會顯示檔案名稱的清單。
在使用者控制項中,按一下 [加入],以將數個項目加入 [TargetList] 清單。
嘗試將已存在與清單中的項目加入 [TargetList] 清單。
已加入重複值。
清除 [允許重複] 方塊,然後再次嘗試加入重複值。
這次重複值未加入 [TargetList] 清單。
按一下 [顯示選取項目]。
[TargetList] 清單中的項目清單隨即顯示在裝載頁面中。
後續步驟
儘管您已建立的控制項不是非常複雜,但可看到許多可以建置至使用者控制項的基本功能。重新調整控制項在很大程度上就是顯示可增強控制項功能的其他屬性和方法。其他成員可能包含下列各項:
外觀屬性。
您可以建立使用者控制項屬性,讓使用者設定控制項的背景、清單大小等。
注意事項: 根據預設,使用者控制項會使用套用至子控制項的目前主題。例如,如果您具有為 Button 控制項定義的面板,則會使用該面板顯示使用者控制項中的按鈕。
資料屬性。
您可加入屬性,讓使用者控制項能夠使用更多種資料在 [SourceList] 清單中顯示。例如,您可加入屬性,以設定資料集、資料表 (Data Table) 和資料顯示欄位。
功能。
您可將更多的按鈕和程式碼加入使用者控制項,讓使用者不僅可複製 [SourceList] 清單的項目至 [TargetList] 清單,還可移動項目 (從 [SourceList] 清單中移除項目,同時將項目移至 [TargetList] 清單)。然後,該控制項可具有能夠將資料從 [TargetList] 清單移回至 [SourceList] 清單的按鈕。
請參閱
工作
HOW TO:將 Web Form 網頁轉換成 ASP.NET 使用者控制項