發布日期: 2006-4-11 | 更新日期: 2006-4-11
Ted Pattison
下載本文的代碼: BasicInstincts0602.exe (763KB)
本頁內容
|
建立用於 ASP.NET 2.0 應用程式的 Web 組件 |
|
設計可串連的 Web 組件 |
|
為一個 Web 組件連接計時 |
|
定義靜態 Web 組件連接 |
|
命名連接點 |
|
動態建立串連 |
當您開始使用 Microsoft .NET Framework 2.0 和 ASP.NET 時,您會發現新的 Web 組件基礎結構將一些非常強大的功能添加到了基礎平台中。在 MSDNMagazine 的 2005 年 9 月號中,我和 Fritz Onion 撰寫了一篇關於對 Web 組件進行編程的文章,題為“ASP.NET 2.0: Personalize Your Portal with User Controls and Custom Web Parts”。在本月的專欄中,我要通過討論 Web 組件連接的工作方式,擴充那篇文章中的資訊。
對於本專欄,我假設您已經對 Web 組件的基本知識有所瞭解,例如,如何使用 WebPartManager 控制項、Web 組件地區、編輯器、目錄和持久性屬性。如果您還不瞭解,建議您在繼續閱讀本文之前先閱讀剛才提到的那篇文章。
建立用於 ASP.NET 2.0 應用程式的 Web 組件
您可以用兩種方法建立 Web 組件。第一種方法涉及建立一個自訂的 Web 組件類,該類從 System.Web.UI.WebControls.WebParts 命名空間中定義的 WebPart 類繼承。使用該方法時,將自訂的 Web 組件類打包到一個程式集 DLL 中通常是有意義的,因為這樣可以提供對重用、版本控制和 Visual Studio 2005 整合的更多控制。如果您對使用以前的 ASP.NET 版本產生自訂控制項很熟悉,則許多相同的技術適用於將自訂的 Web 組件產生到 DLL 程式集中。
用於建立 ASP.NET 2.0 Web 組件的第二種方法涉及使用使用者控制項。雖然該方法不產生相同的重用和版本控制層級,但是它的確允許您使用 Visual Studio 表單設計器來建立 Web 組件的使用者介面部分。如果您想通過將用於使用者輸入、驗證和資料繫結的控制項拖放到設計介面上來建立應用程式,則該方法適合於您。當然,如果您已經花時間建立了一個您想用作 Web 組件的使用者控制項,它也是個可以採用的好方法。
當建立一個專門設計為 Web 組件的使用者控制項時,建議您實現 IWebPart 介面。這樣,Web 組件背景代碼就可通過編程方式分配自己的幾個內部 Web 組件屬性,如它的 Title 和 TitleIconUrl。
本月專欄附帶的程式碼範例使用一個名為 WebPartBase 的自訂基類,該基類從 UserControl 繼承並實現 IwebPart。該基類的定義部署在 App_Code 目錄中名為 WebPartBase.vb 的源檔案中。每當您使用使用者控制項建立一個新 Web 組件時,只需在該程式碼後置檔案中更改該基類以利用該技術:
Partial Class WebParts_CustomersInherits WebPartBaseSub New()Title = "Northwind Customer List"TitleIconImageUrl = "~\img\Customers.gif"End SubEnd Class
返回頁首
設計可串連的 Web 組件
使用 Web 組件連接,您可以使使用者更輕鬆地形象化資料各項之間存在的關係。例如,Web 組件連接可以建模一個主-從方案,其中顯示客戶列表的 Web 組件連接到另一個顯示當前所選客戶詳細資料的 Web 組件。圖 1 的樣本說明這種設計可能產生的使用者介面外觀。
Web 組件連接還可用於建模一對多關聯性。例如,顯示客戶列表的 Web 組件可以串連到另一個顯示針對當前所選客戶的所有定單的 Web 組件。
通常使用 Web 組件連接建模的另一個方案是表單查詢。在這種方案中,一個 Web 組件提供一個使用者介面,該使用者介面允許使用者選取查詢資料(如資料庫表)時所用的搜尋或篩選條件。然後,該 Web 組件連接到另一個顯示查詢結果的 Web 組件。Web 組件連接用於在執行查詢前,將篩選條件從一個 Web 組件傳遞到另一個 Web 組件。
Web 組件連接基於提供者和使用者的概念。提供者 Web 組件通過一個編程介面為一個或多個使用者 Web 組件提供資訊。提供者和使用者之間交換的資訊可以是簡單的資料項目(如數字或字串),也可以是較特殊的內容(如對一個複雜數組或自訂對象集合的引用)。
如果針對 Windows SharePoint Services 2.0 (WSS) 編寫了 Web 組件,您可能已經熟悉它用於串連 Web 組件的模型。在 WSS 中,Web 組件只能使用一組預定義的介面對串連。這些介面對的樣本包括 ICellProvider 和 ICellConsumer,以及 IRowProvider 和 IRowConsumer。
ASP.NET 2.0 中的 Web 組件連接模型比 WSS 中的舊式模型更容易、更靈活,因為您可以使用自己的自訂介面。這意味著您無需使用由 Microsoft 人員建立的介面定義。而且,您無需對介面對進行任何操作,它們必須由提供者和使用者實現。使用 ASP.NET 2.0,只有提供者需要實現一個介面。
要瞭解其工作方式,我們先在兩個 Web 組件之間建立一個串連。對於我要在本月專欄中提供的樣本,我決定使用 Northwind 資料庫,因為它有一個 Customers 表和一個 Orders 表。這使我能為您展示如何針對主-從和一對多關聯性設計 Web 組件。有一點需要注意,如果使用 SQL Server 2005,則在產品安裝過程中並不安裝該樣本 Northwind 資料庫。要安裝它,您必須下載並運行 Microsoft Web 網站上可用的指令碼(請參閱 Microsoft SQL Server 首頁)。
現在,假設您要在一個顯示客戶列表的 Web 組件和一個顯示當前所選客戶的詳細資料的客戶 Web 組件之間建立一個 Web 組件連接,如圖 1所示。顯示客戶列表的 Web 組件將扮演提供者的角色,而顯示當前所選客戶的詳細資料的 Web 組件則作為使用者。在這種情況下,您希望提供者為使用者提供當前所選客戶的 CustomerID 欄位。
首先,建立一個名為 ICustomerIDProvider 的簡單介面:
Public Interface ICustomerIDProviderReadOnly Property CustomerID() As StringEnd Interface
在本月專欄附帶的程式碼範例中,我使用帶有 SqlDataSource 和 GridView 控制項的使用者控制項建立了提供者 Web 組件,以顯示來自 Northwind 的客戶。Web 組件源檔案是 Customers.ascx 和 Customers.ascx.vb,如圖 2 所示。
您可以看到,WebParts_Customers 作為提供者並實現用於該 Web 組件連接的介面。在本例中,WebParts_Customers 實現 ICustomerIDProvider 介面。雖然最常見的模式是提供者本身實現該串連介面,但是它不需要這麼做。唯一的實際要求是,ConnectionProvider 方法返回指定介面的一個執行個體。因此,作為替代方案,該提供者 Web 組件可以返回一個實現該串連介面的 helper 對象。如果一個提供者 Web 組件具有多個介面類型相同的連接點,這通常是有必要的。
通過返回 GridView 控制項的 SelectedDataKey 屬性的值,WebParts_Customers 類實現 CustomerID 屬性。GridView 控制項已經進行了設定以便顯示來自 Northwind Customers 表的記錄,而且它還將 CustomerID 欄位識別為 SelectedDataKey 值。
您應該注意到 WebParts_Customers 類有一個名為 GetCustomerProvider 的方法,該方法具有一個根據 ICustomerIDProvider 介面定義的傳回型別。在這種情況下,由於 Web 組件本身實現所需的介面,因此 GetCustomerProvider 可以只返回對該類的當前執行個體的 Me 引用。您還要注意該方法已經使用 ConnectionProvider 屬性進行了定義:
<ConnectionProvider("Customer ID Provider")>
WebPartManager 負責在運行時串連 Web 組件。當 WebPartManager 看到一個 Web 組件包含一個使用 ConnectionProvider 屬性定義的方法時,它知道該 Web 組件公開一個連接點,因此可以作為提供者並且串連到使用者。當需要將兩個 Web 組件連接在一起時,WebPartManager 將調用 GetCustomerProvider 方法擷取對提供者 Web 組件的強型別引用。
定義一個提供者 Web 組件是否接受到使用者的多個串連是可能的。在某種情況下,一個提供者同時具有到多個使用者的串連是很有用的。在其他情況下,您可能想限制提供者,使它最多可以有一個到使用者 Web 組件的串連。預設情況下,提供者允許多個串連,而使用者則不然。要改變這一點,當您應用 ConnectionProvider 屬性時,可以使用具名引數 AllowsMultipleConnections,如下所示:
<ConnectionProvider("Customer ID Provider", _AllowsMultipleConnections:=False)>
既然您已經看到如何建立一個在提供者 Web 組件中公開連接點的方法,我們來看看這在使用者 Web 組件中是如何?的。使用者 WebPart 通過提供一個使用 ConnectionConsumer 屬性定義的方法來公開連接點。使用者的連接點方法與提供者的串連方法不同,因為它不定義傳回值。相反,它擷取一個用該串連的介面類型定義的參數:
<ConnectionConsumer("Customer ID Consumer")> _Sub RegisterCustomerProvider(ByVal provider As ICustomerIDProvider)... ' implementationEnd Sub
請記住,提供者的連接點方法名稱與使用者的連接點方法名稱並不重要。唯一需要注意的是,每個方法分別使用 ConnectionProvider 屬性和 ConnectionConsumer 屬性進行定義。
現在,我們看看 WebPartManager 在運行時是如何建立該串連的。WebPartManager 調用提供者的連接點方法以擷取對提供者對象的引用。接下來,WebPartManager 調用使用者的連接點方法,以便為它傳遞一個對提供者的強型別引用。
一旦 WebPartManager 完成它的工作之後,使用者 Web 組件就有一個返回到提供者 Web 組件的活動串連。此時,使用者可以使用該引用提供者中定義的方法和屬性,從而與提供者直接互動。但是,ASP.NET 小組建議使用者 Web 組件在 PreRender 階段之前不應使用提供者介面上的方法和屬性。具體說來,它們不應該在 方法本身中使用提供者介面上的方法和屬性。原因是這些串連可能彼此依賴。您可能有一個串連到 ProviderConsumerWebPart 進而串連到 ConsumerWebPart 的 ProviderWebPart。在這兩個串連建立之前,ConsumerWebPart 無法查詢提供者介面,而且串連建立的順序取決於架構。
圖 3 顯示 CustomerDetails.ascx.vb 中使用者 Web 組件的完整代碼清單。您可以看到,使用者 Web 組件負責持續引用,以便可以跟蹤到提供者的串連。該使用者 Web 組件包含一個名為 provider 的私人欄位,該欄位是根據 ICustomerIDProvider 介面定義的。
當 WebPartManager 調用 RegisterCustomerProvider 時,使用者擷取傳入的引用參數並將它分配給提供者欄位。當提供者欄位分得該引用後,使用者 Web 組件就可以與提供者 Web 組件直接互動。為串連設計該介面時,您應該添加將提供您所需互動的任何方法和屬性。
在某些情況下,使用者 Web 組件可能設計為無論是否有到提供者的活動串連都正常工作。在這種設計中,當提供者欄位有一個 Nothing 值時,您可能希望將臨時代碼添加到正常工作的使用者 Web 組件中:
If provider IsNot Nothing Then... ' interact with providerElse... ' contingency code goes here if requiredEnd If
返回頁首
為一個 Web 組件連接計時
當您開始設計支援串連的 Web 組件時,瞭解所涉及的計時是非常重要的。圖 4 顯示在 HTTP GET 期間運行提供者 Web 組件和使用者 Web 組件的頁面的一小部分。雖然有更多在 HTTP POST 期間激發的頁面級事件,但是串連建立時的計時則保持相同。
圖 4 中顯示的跟蹤資訊闡釋了對於標準的 ASP.NET 2.0 頁面級事件而言,每個串連方法何時激發。您應該能夠從該跟蹤資訊中看到,WebPartManager 在頁面級 LoadComplete 命令中將 Web 組件連接在一起。
需要牢記的是,當頁面級事件 PreInit、Init、PreLoad 和 Load 執行時,Web 組件連接尚未建立。這意味著您絕不應該嘗試訪問使用者 Web 組件的處理常式方法(它綁定到這些事件之一)中的提供者。在嘗試訪問提供者 Web 組件之前,使用者 Web 組件中的代碼必須等待 LoadComplete 事件執行完畢。
在本樣本中,使用者 Web 組件處理 SqlDataSource 控制項的 Selecting 事件,該事件在頁面級 PreRender 事件中激發。此時,訪問提供者並檢索客戶 ID 是安全的。
返回頁首
定義靜態 Web 組件連接
既然您已經看到如何建立支援串連的 Web 組件,並且瞭解了所涉及的計時,現在該探究如何將它們實際串連在一起了。您將看到,可以將標記直接添加到一個 Web 組件頁面定義中,以便建立一個靜態 Web 組件連接。也可以在運行時通過代碼或使用者互動動態建立 Web 組件連接。首先,我要展示如何在兩個 Web 組件之間建立一個靜態串連,因為這是最簡單的方法。
要在一個頁面上的兩個 Web 組件之間建立靜態 Web 組件連接,需要將 StaticConnections 元素添加到 WebPartManager 標記中:
<asp:WebPartManager ID="WebPartManager1" runat="server"><StaticConnections><asp:WebPartConnection ID="c1"ProviderID="Customers1"ConsumerID="CustomerDetails1" /></StaticConnections></asp:WebPartManager>
要使該代碼正常運行,名為 Customers1 的提供者 Web 組件和名為 CustomerDetails1 的使用者 Web 組件也必須在同一頁面上的 Web 組件地區中靜態定義和正確命名。
需要牢記的是,每個頁面只有一個 WebPartManager 控制項。然而,在許多涉及 Web 組件的應用程式設計中,您會發現將 WebPartManager 添加到使用者控制項或主版頁面很方便,原因是可以在許多頁面上重用它。
當 Web 組件頁面基於主版頁面,或者使用的是包含 WebPartManager 控制項的使用者控制項時,您不能添加 WebPartManager 控制項的第二個樣本來定義 StaticConnections 標記。針對這些情況,ASP.NET 2.0 Web 組件控制集提供了 ProxyWebPartManager 控制項。以下是關於如何使用它的樣本:
<asp:ProxyWebPartManager ID="ProxyWebPartManager1" runat="server"><StaticConnections><asp:WebPartConnection ID="c1"ProviderID="Customers1"ConsumerID="CustomerDetails1" /></StaticConnections></asp:ProxyWebPartManager>
ProxyWebPartManager 控制項的價值在於,它允許您在頁面無法包含 WebPartManager 標記時,在頁面級添加靜態串連。在本專欄附帶的樣本頁面 default.aspx 中,必須使用 ProxyWebPartManager 建立一個靜態 Web 組件連接,原因是 WebPartManager 已經封裝在名為 WebPartManagerPanel.ascx 的使用者控制項中。
返回頁首
命名連接點
在我目前產生的樣本中,提供者 Web 組件和使用者 Web 組件之間的串連已經基於預設的連接點。但是,Web 組件連接方法提供一個命名連接點是可能的。要將一個命名連接點添加到提供者,您只需將第二個字串參數添加到 ConnectionProvider 屬性:
<ConnectionProvider("Customer ID Provider", "CustomerIDProvider")> _Public Function GetCustomerProvider() As ICustomerIDProviderReturn MeEnd Function
之所以使用命名連接點的一個原因是提供者或使用者可能有多個連接點,因此必須能區分它們。要將一個命名連接點添加到使用者 Web 組件,您可以將第二個字串參數添加到 ConnectionConsumer 屬性:
<ConnectionConsumer("Customer ID" & "Consumer", "CustomerIDConsumer")> _Sub RegisterCustomerProvider(ByVal provider As ICustomerIDProvider)Me.provider = providerEnd Sub
當您開始使用命名連接點時,在頁面級定義 StaticConnections 標記時,必須為 ProviderConnectionPointID 和 ConsumerConnectionPointID 提供兩個額外的屬性值。
返回頁首
動態建立串連
當您想將 Web 組件連接在一起時,有時卻無法依賴靜態 Web 組件連接。例如,如果您想串連通過自訂代碼動態建立的 Web 組件,或者由使用 Web 組件目錄將 Web 組件添加到頁面的使用者動態建立的 Web 組件,就會出現這種情況。
在無法使用靜態 Web 組件連接時,您必須使用動態技術串連 Web 組件。為此,可以使用自訂代碼,或者使用 ASP.NET 2.0 Web 組件控制集附帶的 ConnectionsZone 控制項。
讓我們首先看一下建立兩個 Web 組件並將它們動態串連在一起的自訂代碼,如圖 5 所示。該代碼通過使用者控制項為提供者和使用者建立了 Web 組件執行個體,並將它們添加到宿主 Web 組件頁面的現有 Web 組件地區。然後,該代碼在它們之間建立一個串連。請注意,Web 組件和串連將儲存為使用者個人化資訊的一部分,因此它們應該只添加到 WebPartManager 一次。如果您不想以這種方式儲存 Web 組件和串連,也可以使用其他 API。
圖 6 串連顯示模式
您可以看到,圖 5 中顯示的技術需要使用 ProviderConnectionPoint 對象和 ConsumerConnectionPoint。通過調用 WebPartManager 提供的方法並傳遞那些命名連接點的字串標識符,可以檢索這些對象。
您和您的使用者可以用來建立動態 Web 組件連接的另一種技術涉及到 ConnectionsZone 控制項。要有效地使用該技術,您應該建立一個 Web 組件頁面,其右側有一個包含 ConnectionsZone 控制項的工作窗格。當使用者使該頁面處於串連視圖顯示模式中時,Connect 命令將添加到公開連接點的每個 Web 組件的 Web 組件菜單中, 6 所示。
當使用者選擇 Connect 命令時,Web 組件頁面會顯示 ConnectionsZone 控制項,並允許使用者查看該頁面上所有可串連的 Web 組件的所有相容連接點(請參見圖 7)。使用該技術,您可以將使用者串連到提供者。同樣,您也可以將提供者串連到使用者。
請將有關 Ted 的問題和意見發送至 instinct@Microsoft.com。
Ted Pattison 是一位作家兼講師,他通過自己的公司提供動手培訓,他的公司名為 Ted Pattison Group。Ted 目前正在研究和撰寫一本新書,著重於介紹 Windows SharePoint Services "V3" 和 Office 12 伺服器技術。