原文發表在http://dev.yesky.com/msdn/351/2163851.shtml?412,新編譯的一篇關於asp.net 2.0中webpart的文章:
在現在的網站設計中,更強調的是使用者的個人化,讓使用者可以自由的設定符合自己喜好的頁面成為網站開發人員的頭號難題,不過現在看來這個難題微軟幫我們解決了。在asp.net 2.0中新增加了一系列webpart控制項,可以讓使用者很方便地對網頁的各地區布局進行調整。在一些web應用程式中,如果使用者想自訂頁面配置,比如一個新聞發布系統,想讓左,中,右三欄的位置進行調換的話,就可以使用webpart控制項。
下面,我們來看下asp.net 2.0中webpart系列控制項的一些基本用法。
首先,在vs.net 2005 中的工具箱中,可以找到如所示的webpart系列控制項,有很多個,限於篇幅,本文介紹其中的一些重要的控制項:
在webpart系列控制項中,其中的webpartmanager控制項用於統一管理各webpart控制項。而webpartzone控制項,則是提供了各地區劃分,在這些地區中,使用者可以往裡面放置各式各樣的控制項,而當啟動並執行時候,使用者可以移動的就是這些webpartzone控制項所在的地區。
為增強認識,我們先做個簡單的例子。
1、首先使用vs.net 2005 beta 2(或者RC1)建立一個web網站,
2、往表單中拖拉一個webpartmanager控制項,再建一個3列1行的表格,分別往每個儲存格裡拖拉一個webpartzone控制項,如:
3、往webpartzone1中拖拉放一個日曆控制項,並為這個日曆控制項選擇一個合適的樣式
4、切換到程式碼檢視狀態,將日曆控制項的title屬性改為:today’s date。注意的是,日曆控制項本身沒有title屬性,但當一個控制項加入到webpartzone地區中去後,則該控制項被自動封裝為GenericWebPart類型控制項,這些類型的控制項有title屬性。
5、這時,我們可以按F5來運行該程式,運行如所示,可以看到,地區的右上方有最小化和關閉,恢複的按鈕。
接下來,我們介紹如何在webpart系列控制項中,使用使用者自訂的控制項。
1、首先,我們為工程項目增加一個"google.ascx"的控制項,並且在images目錄下,添加google那張著名的logo圖片。
接著,往表單中添加一個2*2行的表格,再往其中的一個儲存格添加一個image圖象控制項,指定其圖象為google.gif,再添加一個文字框,一個按鈕,如所示,其中,括弧內的是該控制項的名稱:
3、在btnsearch按鈕的click事件中寫入如下代碼:
Response.Write(Page.IsValid) Dim queryStr As String = HttpUtility.UrlEncode(txtSearch.Text) Response.Redirect("http://www.google.com/search?q=" & queryStr) End Sub |
4、這時,將寫好的google.ascx控制項,整個拖拉到我們剛才建立好的表格中的中間那個儲存格,如所示:
我們並且修改代碼如下,修改其名稱為google serach:
| <uc1:Google title="Google Search" runat="server" ID="Google1" /> |
接下來,F5運行,可以看到,可以在googlesearch所在的webpart裡進行google搜尋了。
同時,如果覺得webpart的那些關閉,恢複,最小化的按鈕不大好看,還可以自訂按鈕,比如在images目錄下,添加下面的圖片:
然後,在webpartzone1的屬性中,指定如下的屬性就可以了。
CloseVerb.ImageUrl="Images/CloseVerb.gif" EditVerb.ImageUrl="Images/EditVerb.gif" MinimizeVerb.ImageUrl="Images/MinimizeVerb.gif" RestoreVerb.ImageUrl="Images/RestoreVerb.gif" |
使webpart動起來
上面設計的webpart還沒能動起來,要讓webpart動起來的話,必須要將webpar設定為design display 模式。先為webpart添加下面的radiobutton選擇框
<asp:RadioButtonList ID="rblMode" runat="server" AutoPostBack="True"> <asp:ListItem>Browse Display Mode</asp:ListItem> <asp:ListItem>Design Display Mode</asp:ListItem> </asp:RadioButtonList> |
並且在code-behind的代碼中,寫入如下代碼:
Protected Sub RadioButtonList1_SelectedIndexChanged(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles rblMode.SelectedIndexChanged Select Case rblMode.SelectedIndex Case 0 : WebPartManager1.DisplayMode =WebPartManager.BrowseDisplayMode Case 1 : WebPartManager1.DisplayMode = WebPartManager.DesignDisplayMode End Select End Sub |
運行上面代碼,選擇design display mode,則可以象那樣,自由拖動webpart,
要注意的是,當移動各webpart的位置後,即使關掉瀏覽器,下次重新開啟時,依然可以看到各個控制項保持原來的位置。其實,asp.net 2.0是使用在aspnetdb.mdf中的一個叫aspnet_PersonalizationPerUser的表來儲存資料的,表的結構如下所示:
| Field |
Value |
| Id |
928e121a-4042-4fb4-9520-21210b9b37c1 |
| PathId |
7c3b5dc0-04d0-48a2-bbb2-2b70286f22fe |
| UserId |
9bff14df-024f-4bda-9a0a-b4a19ab9e387 |
| PageSettings |
<Binary data> |
| LastUpdatedDate |
10/06/2005 4:44:05 AM |
如果想恢複各控制項的原來位置,只需要將該資料表中相應的行刪除掉就可以了。但有個問題是,如果使用每一個webpart的關閉按鈕,則很難再將其恢複(當然刪除資料表中的行,但十分麻煩)。在asp.net 2.0中,提供了另一種webpart,叫做catlogzone控制項,下面介紹其用法
1、往表單中拖拉一個catlogzone控制項,如所示。
2、往該catlogzone控制項地區中,再拖放三個webpart系列的控制項,分別是DeclarativeCatalogPart, PageCatalogPart, and ImportCatalogPart,如所示。其中,DeclarativeCatalogPart控制項的作用是,顯示目前頁面上有哪些可以用的webpart控制項;PageCatalogPart的作用是,可以讓使用者通過勾選的方式,選定將哪些控制項添加轉移到其他webpart地區中去。ImportCatalogPart則可以通過外部磁碟檔案的方式,載入其他做好了的webpart組件
3、在radiobutton地區中,修改以下代碼,增添一個catalog display的顯示模式:
<asp:RadioButtonList ID="rblMode" runat="server" AutoPostBack="True"> <asp:ListItem>Browse Display Mode</asp:ListItem> <asp:ListItem>Design Display Mode</asp:ListItem> <asp:ListItem>Catalog Display Mode</asp:ListItem> </asp:RadioButtonList> |
然後,在code-behind的代碼中,將代碼修改為如下:
Protected Sub rblMode_SelectedIndexChanged( _ ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles rblMode.SelectedIndexChanged Select Case rblMode.SelectedIndex Case 0 : WebPartManager1.DisplayMode = WebPartManager.BrowseDisplayMode Case 1 : WebPartManager1.DisplayMode = WebPartManager.DesignDisplayMode Case 2 : WebPartManager1.DisplayMode = WebPartManager.CatalogDisplayMode End Select End Sub |
4、在DeclarativeCatalogPart任務菜單上,點擊右上方的智能感知按鈕,然後選"edit templates"的連結,進入模版編輯狀態,如:
再往其中的webpartstemplate地區中拖拉一個google.ascx控制項,如,這將允許使用者在運行時,可以自由地往頁面增加這樣的google搜尋控制項。
5、然後修改代碼如下:
<ZoneTemplate> <asp:DeclarativeCatalogPart ID="DeclarativeCatalogPart1" runat="server"> <WebPartsTemplate> <uc1:Google title="Google Search" ID="Google2" runat="server" /> </WebPartsTemplate> </asp:DeclarativeCatalogPart> |
6、運行程式,可以看到,當選擇catalog display mode時,會顯示如所示的catalog zone,其中列出了當前可用的有哪些webpart控制項,我們可以把這個google的控制項加到其他的webpart地區,也可以嘗試將已經存在的webpart控制項關閉,然後在catalog zone地區中的控制項列表中,把它們再加回到頁面中去。
此外,在運行期間,還可以動態地修改webpart控制項的外觀等屬性,如下:
1) 往表單中添加一個editor zone的地區控制項,往其中再拖放一個appearanceEdiotrPart控制項,該控制項可以在運行時,讓使用者動態改變各webpart控制項的屬性。
2) 我們再修改radiobutton選擇框的代碼如下,則加一個編輯模式:
<asp:RadioButtonList ID="rblMode" runat="server" AutoPostBack="True"> <asp:ListItem>Browse Display Mode</asp:ListItem> <asp:ListItem>Design Display Mode</asp:ListItem> <asp:ListItem>Catalog Display Mode</asp:ListItem> <asp:ListItem>Edit Display Mode</asp:ListItem> </asp:RadioButtonList> |
3) 修改code-behind代碼如下:
Protected Sub rblMode_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) _ Handles rblMode.SelectedIndexChanged Select Case rblMode.SelectedIndex Case 0 : WebPartManager1.DisplayMode = WebPartManager.BrowseDisplayMode Case 1 : WebPartManager1.DisplayMode = WebPartManager.DesignDisplayMode Case 2 : WebPartManager1.DisplayMode = WebPartManager.CatalogDisplayMode Case 3 : WebPartManager1.DisplayMode = WebPartManager.EditDisplayMode End Select End Sub |
4) 運行程式,選擇edit display mode模式,這時,會發現每個控制項的右上方,會多了一個"edit"的按鈕,點該按鈕,彈出如的表單,使用者可以修改每個控制項的外觀等屬性。
最後,我們看下,webpart控制項之間還可以進行相互之間的通訊,下面的例子中,要實現的是,在一個日曆控制項中點選某一個日期,會在已經做好的googlesearch的webpart控制項的文字框中顯示其日期,達到通訊的目的,下面介紹其實現步驟:
1、為了使兩個webpart控制項之間進行通訊,必須先聲明一個公用的介面。往工程項目裡增加一個叫ISelectedDate.vb的類檔案,放在app_code目錄下,寫入如下代碼:
Imports Microsoft.VisualBasic Public Interface ISelectedDate ReadOnly Property SelectedDate( ) As Date End Interface |
這裡,我們返回一個唯讀日期屬性selectedDate.
2、再建立一個日曆控制項CalendarUC.ascx,其中拖拉一個普通的日曆控制項即可。然後寫入如下代碼:
Partial Class CalendarUC_ascx Inherits System.Web.UI.UserControl Implements ISelectedDatePublic ReadOnly Property SelectedDate( ) As Date Implements ISelectedDate.SelectedDate Get Return Calendar1.SelectedDate.Date End Get End Property <ConnectionProvider("SelectedDate", "SelectedDate")> _ Public Function GetSelectedDate( ) As ISelectedDate Return Me End Function End Class |
上面的代碼,首先實現了已經聲明了的IselectedDate介面,要留意的是<ConnectionProvider("SelectedDate", "SelectedDate")>中的寫法。由於在這個例子中,日曆控制項要為其他的控制項提供資訊,因此,該日曆控制項是一個provider(提供者),而另外的接收資訊的控制項,是consumer(消費者)。而兩者為了要通訊,必須要提供一個通訊存取點,就象一個電插頭,要找到合適的電插板一樣。因此,<ConnectionProvider("SelectedDate", "SelectedDate")>中的第一個參數,定義了兩者的介面點,第二個參數,則是要傳遞給consumer的參數,本例是selectedDate。
3、接下來,我們在已經做好的google.ascx控制項的代碼中,編寫如下代碼:
| Private _selectedDate As ISelectedDate <ConnectionConsumer("SelectedDate", "SelectedDate")> _ Sub setSearchText(ByVal SearchText As ISelectedDate) Me._selectedDate = SearchText End Sub Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender If _selectedDate IsNot Nothing Then txtSearch.Text = _selectedDate.SelectedDate.ToShortDateString End If End Sub |
可以看到 <ConnectionConsumer("SelectedDate", "SelectedDate")>的定義必須和provider中的定義一樣。
4、再修改如下代碼,將兩個控制項的命名變得通俗易懂
<ZoneTemplate> <uc1:Google title="Google Search" runat="server" ID="Google1" /> <uc3:CalendarUC title="Calendar Web Part" runat="server" ID="CalendarUC1" /> </ZoneTemplate> |
5、最後,為了使兩者能互相通訊,必須在default.aspx頁中修改如下代碼:
<asp:WebPartManager ID="WebPartManager1" runat="server"> <StaticConnections> <asp:WebPartConnection ID="Connection" ProviderID="CalendarUC1" ProviderConnectionPointID="SelectedDate" ConsumerID="Google1" ConsumerConnectionPointID="SelectedDate" /> </StaticConnections> </asp:WebPartManager> |
6、在頁面代碼中,增加一個radiobutton,用作顯示connection模式,並寫入如下代碼:
| Case 4 : WebPartManager1.DisplayMode = WebPartManager.ConnectDisplayMode |
7、運行程式,選擇connect displaymode模式。再選擇GOOGLE SEARCH的那個webpart控制項,點右上方的"conenct"按鈕,此時,會顯示如所示,提示你要選擇從那個控制項中得到資訊,這裡選擇日曆控制項,按確定。那麼,當點選日曆控制項的某個日期值的時候,GOOGLE SEARCH的那個文字框裡,就會顯示相應的日期了。