共用方式為


從主版頁面與內容頁互動 (C#)

由斯科特· 米切爾

檢查如何從主版頁面中的程式代碼呼叫方法、設定屬性等內容頁面。

簡介

上述教學課程已檢查如何以程序設計方式讓內容頁面與其主版頁面互動。 回想一下,我們已更新主版頁面,以包含列出五個最近新增產品的 GridView 控制件。 然後,我們建立了內容頁面,讓使用者可以從中新增新產品。 新增新產品時,需要指示主版頁面重新整理其 GridView,使其包含剛新增的產品。 這項功能是藉由將公用方法新增至主版頁面,以重新整理系結至 GridView 的數據,然後從內容頁面叫用該方法來完成。

最常見的內容形式和主版頁面互動源自內容頁面。 不過,主版頁面可能會讓目前的內容頁面變成作用,而且如果主版頁面包含使用者介面元素,則可能需要這類功能,讓使用者修改內容頁面上也顯示的數據。 請考慮在 GridView 控件中顯示產品資訊的內容頁面,以及包含按鈕控件的主版頁面,按兩下時,會將所有產品的價格加倍。 與上一個教學課程中的範例類似,在按下雙價按鈕之後,必須重新整理 GridView,才能顯示新的價格,但在此案例中,主版頁面需要讓內容頁面生效。

本教學課程會探索如何讓主版頁面叫用功能定義於內容頁面中。

透過事件和事件處理程式煽動程式設計互動

從主版頁面叫用內容頁面功能比另一種方式更具挑戰性。 因為內容頁面有單一主版頁面,因此從內容頁面煽動程式設計互動時,我們知道我們可以使用哪些公用方法和屬性。 不過,主版頁面可以有許多不同的內容頁面,每個頁面都有自己的一組屬性和方法。 然後,如何在主版頁面中撰寫程式代碼,以在不知道在運行時間之前叫用哪些內容頁面時,在其內容頁面中執行一些動作?

請考慮 ASP.NET Web 控件,例如 Button 控件。 按鈕控制項可以出現在任意數目的 ASP.NET 頁面上,而且需要一個機制,其可以警示已按下的頁面。 這是使用 事件來完成的。 特別是,Button 控件在按兩下時會引發其 Click 事件;包含 Button 的 ASP.NET 頁面可以選擇性地透過 事件處理程式響應該通知。

這個相同模式可用來在其內容頁面中具有主版頁面觸發程式功能:

  1. 將事件新增至主版頁面。
  2. 每當主版頁面需要與其內容頁面通訊時,引發 事件。 例如,如果主版頁面需要提醒其內容頁面使用者已將價格加倍,則會在價格翻倍之後立即引發其事件。
  3. 在這些需要採取一些動作的內容頁面中建立事件處理程式。

本教學課程的其餘部分會實作簡介中所述的範例;也就是說,列出資料庫中產品的內容頁面,以及包含按鈕控件以加倍價格的主版頁面。

步驟 1:在內容頁面中顯示產品

我們的第一個業務順序是建立內容頁面,以列出 Northwind 資料庫中的產品。 (我們在上一個教學課程中將 Northwind 資料庫新增至專案, 從內容頁面與主版頁面互動。首先,將新的 ASP.NET 頁面新增至 ~/Admin 名為 Products.aspx的資料夾,請務必將它系結至 Site.master 主版頁面。 圖 1 顯示此頁面新增至網站之後的 方案總管。

將新的 ASP.NET 頁面新增至管理資料夾

圖 01:將新的 ASP.NET 頁面新增至 Admin 資料夾 (按一下以檢視完整大小的影像

回想一下,在主版頁面教學課程中指定標題、中繼標記和其他 HTML 標頭教學課程中,我們建立了名為 BasePage 的自定義基頁類別,如果未明確設定,就會產生頁面的標題。 移至 Products.aspx 頁面的程式代碼後置類別,並讓它衍生自 BasePage (而不是 衍生自 System.Web.UI.Page)。

最後,更新 Web.sitemap 檔案以包含本課程的專案。 將下列標記新增至主版頁面互動課程的 下方 <siteMapNode>

<siteMapNode url="~/Admin/Products.aspx" title="Master to Content Page Interaction" />

新增此 <siteMapNode> 元素會反映在 Lessons 清單中(請參閱圖 5)。

Products.aspx傳回 。 在 的內容控制項 MainContent中,新增 GridView 控制項並將其命名為 ProductsGrid。 將 GridView 系結至名為 ProductsDataSource的新 SqlDataSource 控制件。

將 GridView 系結至新的 SqlDataSource 控制件

圖 02:將 GridView 系結至新的 SqlDataSource 控件(按兩下以檢視完整大小的影像

設定精靈,使其使用 Northwind 資料庫。 如果您已完成上一個教學課程,則應該已在 中Web.config擁有名為 NorthwindConnectionString 的 連接字串。 從下拉式清單中選擇此 連接字串,如圖 3 所示。

將 SqlDataSource 設定為使用 Northwind 資料庫

圖 03:將 SqlDataSource 設定為使用 Northwind 資料庫 (按兩下以檢視完整大小的影像

接下來,從下拉式清單中選擇 Products 資料表並傳ProductName回 和 UnitPrice 資料行,以指定數據源控件的SELECT語句(請參閱圖 4)。 按 [下一步],然後按擊 [完成] 以完成 [設定數據源精靈]。

從 Products 數據表傳回 ProductName 和 UnitPrice 字段

圖 04:從Products資料表傳ProductName回 和 UnitPrice 字位 (按兩下以檢視完整大小的影像

這樣就全部完成了! 完成精靈之後,Visual Studio 會將兩個 BoundFields 新增至 GridView,以鏡像 SqlDataSource 控件傳回的兩個字段。 GridView 和 SqlDataSource 控件的標記如下。 圖 5 顯示透過瀏覽器檢視時的結果。

<asp:GridView ID="ProductsGrid" runat="server" AutoGenerateColumns="False" 
 DataSourceID="ProductsDataSource">
 <Columns>
 <asp:BoundField DataField="ProductName" HeaderText="ProductName" 
 SortExpression="ProductName" />
 <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" 
 SortExpression="UnitPrice" />
 </Columns>
</asp:GridView>

<asp:SqlDataSource ID="ProductsDataSource" runat="server" 
 ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" 
 SelectCommand="SELECT [ProductName], [UnitPrice] FROM [Products]">
</asp:SqlDataSource>

每個產品及其價格都會列在 GridView 中

圖 05:每個產品及其價格都列在 GridView 中(按兩下以檢視完整大小的影像

注意

您可以隨意清除 GridView 的外觀。 某些建議包括將顯示的 UnitPrice 值格式化為貨幣,以及使用背景色彩和字型來改善網格線的外觀。 如需在 ASP.NET 中顯示和格式化數據的詳細資訊,請參閱我的 使用數據教學課程系列

步驟 2:將雙價按鈕新增至主版頁面

下一項工作是將 Button Web 控制項新增至主版頁面,當按兩下時,將會將資料庫中所有產品的價格加倍。 Site.master開啟主版頁面,並將 [按鈕] 從 [工具箱] 拖曳到設計工具上,將它放在我們在上一個教學課程中新增的 RecentProductsDataSource SqlDataSource 控件之下。 將 Button 的 ID 屬性設定為 DoublePrice ,並將其 Text 屬性設定為 「Double Product Prices」。。

接下來,將 SqlDataSource 控制項新增至主版頁面,並將它命名為 DoublePricesDataSource。 此 SqlDataSource 將用來執行 UPDATE 語句,將所有價格加倍。 具體而言,我們需要將其 ConnectionStringUpdateCommand 屬性設定為適當的 連接字串 和UPDATE語句。 然後,當按兩下 Button 時DoublePrice,我們需要呼叫這個 SqlDataSource 控制件Update的方法。 若要設定 ConnectionStringUpdateCommand 屬性,請選取 SqlDataSource 控件,然後移至 屬性視窗。 屬性ConnectionString會列出已儲存在Web.config下拉式清單中之 連接字串;請選擇NorthwindConnectionString如圖 6 所示的選項。

將 SqlDataSource 設定為使用 NorthwindConnectionString

圖 06:將 SqlDataSource 設定為 [使用 NorthwindConnectionString ] (按兩下以檢視完整大小的影像

若要設定 UpdateCommand 屬性,請在 屬性視窗 中找到 UpdateQuery 選項。 選取此屬性時,會顯示具有省略號的按鈕;按下此按鈕,即可顯示圖 7 中顯示的 [命令和參數編輯器] 對話方塊。 在對話框的文字框中輸入下列 UPDATE 語句:

UPDATE Products SET UnitPrice = UnitPrice * 2

執行這個語句時,會將數據表中Products每筆記錄的值加倍UnitPrice

設定 SqlDataSource 的 UpdateCommand 屬性

圖 07:設定 SqlDataSource 的 UpdateCommand 屬性 (按兩下以檢視完整大小的影像

設定這些屬性之後,Button 和 SqlDataSource 控件的宣告式標記看起來應該如下所示:

<asp:Button ID="DoublePrice" runat="server" 
 Text="Double Product Prices" />

<asp:SqlDataSource ID="DoublePricesDataSource" runat="server" 
 UpdateCommand="UPDATE Products SET UnitPrice = UnitPrice * 2" 
 ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" 
 ProviderName="<%$ ConnectionStrings:NorthwindConnectionString.ProviderName %>">
</asp:SqlDataSource>

所有剩餘專案都是在按兩下按鈕時DoublePrice呼叫其Update方法。 建立 Click Button 的 DoublePrice 事件處理程式,並新增下列程式代碼:

protected void DoublePrice_Click(object sender, EventArgs e)
{
    // Double the prices
    DoublePricesDataSource.Update();
}

若要測試這項功能,請流覽 ~/Admin/Products.aspx 我們在步驟 1 中建立的頁面,然後按兩下 [雙重產品價格] 按鈕。 按兩下按鈕會導致回傳並執行 DoublePrice Button 的 Click 事件處理程式,將所有產品的價格加倍。 然後重新轉譯頁面,並在瀏覽器中傳回標記並重新顯示。 不過,內容頁面中的 GridView 會列出與按下 [雙重產品價格] 按鈕之前相同的價格。 這是因為最初載入 GridView 中的數據已將其狀態儲存在檢視狀態中,因此除非另有指示,否則不會重載回傳。 如果您流覽不同的頁面,然後返回 ~/Admin/Products.aspx 頁面,您會看到更新的價格。

步驟 3:當價格翻倍時引發事件

因為頁面中的 ~/Admin/Products.aspx GridView 不會立即反映價格翻一番,所以使用者可以理解地認為他們沒有按兩下 [雙重產品價格] 按鈕,或它無法運作。 他們可能會再試一次按鍵,一次又一次地將價格翻倍。 若要修正此問題,我們需要在內容頁面中的方格在兩倍之後立即顯示新的價格。

如本教學課程稍早所述,每當用戶按下 DoublePrice 按鈕時,我們需要在主版頁面中引發事件。 事件是一個類別(事件發行者)通知另一組其他類別(事件訂閱者)發生有趣事件的方法。 在此範例中,主版頁面是事件發行者;那些在按兩下 [按鈕] 時 DoublePrice 所關心的內容頁面是訂閱者。

類別會藉由建立 事件處理程式來訂閱事件,這是為了回應所引發事件而執行的方法。 發行者藉由定義事件委派來定義他所引發的事件。 事件委派會指定事件處理程序必須接受哪些輸入參數。 在 .NET Framework 中,事件委派不會傳回任何值,並接受兩個輸入參數:

  • Object,識別事件來源和
  • 衍生自的類別 System.EventArgs

傳遞至事件處理程式的第二個參數可以包含事件的其他資訊。 雖然基 EventArgs 類不會傳遞任何資訊,但 .NET Framework 包含一些可擴充 EventArgs 及包含其他屬性的類別。 例如,實例會傳遞至回應Command事件的事件處理程式,並包含兩個CommandEventArgs參考屬性:CommandArgumentCommandName

注意

如需建立、引發及處理事件的詳細資訊,請參閱簡單英文的事件和委派和事件委派。

若要定義事件,請使用下列語法:

public event eventDelegate eventName;

因為我們只需要在使用者按兩下 DoublePrice Button 時發出警示內容頁面,而且不需要傳遞任何其他資訊,所以我們可以使用 事件委派 EventHandler,這個委派會定義事件處理程式,該事件處理程式會接受做為其第二個參數的 型 System.EventArgs別物件。 若要在主版頁面中建立事件,請將下列程式代碼行新增至主版頁面的程式代碼後置類別:

public partial class Site : System.Web.UI.MasterPage
{
    public event EventHandler PricesDoubled;

    ...
}

上述程式代碼會將公用事件新增至名為 PricesDoubled的主版頁面。 我們現在需要在價格翻倍后提高這個事件。 若要引發事件,請使用下列語法:

if (eventName != null)
    eventName(sender, eventArgs);

其中 sendereventArgs 是您想要傳遞至訂閱者事件處理程式的值。

DoublePrice Click使用下列程式代碼更新事件處理程式:

protected void DoublePrice_Click(object sender, EventArgs e)
{
    // Double the prices
    DoublePricesDataSource.Update();

    // Refresh RecentProducts
    RecentProducts.DataBind();

    // Raise the PricesDoubled event
    if (PricesDoubled != null)
    PricesDoubled(this, EventArgs.Empty);
}

和之前一樣,事件處理程式一 Click 開始會呼叫 DoublePricesDataSource SqlDataSource 控件的 Update 方法來將所有產品的價格加倍。 之後,事件處理程式有兩個新增專案。 首先, RecentProducts GridView 的數據會重新整理。 此 GridView 已新增至上一個教學課程的主版頁面,並顯示五個最近新增的產品。 我們需要重新整理此方格,使其顯示這五個產品的 Just-doubled 價格。 之後, PricesDoubled 就會引發 事件。 主版頁面本身的參考 (this) 會當做事件來源傳送至事件處理程式,而空白 EventArgs 物件會當做事件自變數傳送。

步驟 4:處理內容頁面中的事件

此時,每當DoublePrice按鍵控件時,主版頁面就會引發其PricesDoubled事件。 然而,這隻是一半的戰鬥 - 我們仍然需要處理訂閱者的事件。 這牽涉到兩個步驟:建立事件處理程式並新增事件連接程序代碼,以便在引發事件時執行事件處理程式。

首先,建立名為的 Master_PricesDoubled事件處理程式。 由於我們在主版頁面中定義 PricesDoubled 事件的方式,事件處理程式的兩個輸入參數必須分別是 型 Object 別和 EventArgs。 在事件處理程式中, ProductsGrid 呼叫 GridView 的 DataBind 方法來將數據重新繫結至方格。

private void Master_PricesDoubled(object sender, EventArgs e)
{
    // Rebind data to ProductsGrid
    ProductsGrid.DataBind();
}

事件處理程式的程式代碼已完成,但我們尚未將主版頁面的事件 PricesDoubled 連線至這個事件處理程式。 訂閱者會透過下列語法將事件連線至事件處理程式:

publisher.eventName += new eventDelegate(methodName);

publisher 是提供 eventName 之對象的參考,而 methodName 是訂閱者中定義的事件處理程式名稱,其簽章對應至 eventDelegate。 換句話說,如果事件委派是 EventHandler,則 methodName 必須是訂閱者中未傳回值的方法名稱,並且分別接受兩個型 Object 別和 EventArgs的輸入參數。

此事件連接程式代碼必須在第一頁瀏覽和後續回傳上執行,而且應該發生在事件可能引發之前的頁面生命週期中某個時間點。 新增事件線路程序代碼的好時機是在 PreInit 階段中,這會在頁面生命週期中非常早發生。

開啟 ~/Admin/Products.aspx 並建立 Page_PreInit 事件處理程式:

protected void Page_PreInit(object sender, EventArgs e)
{
    // TODO: Put event wiring logic here
}

為了完成此連接程式代碼,我們需要從內容頁面以程式設計方式參考主版頁面。 如上一個教學課程所述,有兩種方式可以執行這項操作:

  • 將鬆散類型 Page.Master 屬性轉換成適當的主版頁面類型,或
  • 在頁面中新增 @MasterType 指示詞 .aspx ,然後使用強型別 Master 屬性。

讓我們使用後者的方法。 將下列 @MasterType 指示詞新增至頁面宣告式標記頂端:

<%@ MasterType VirtualPath="~/Site.master" %>

然後在事件處理程式中 Page_PreInit 新增下列事件連接程式代碼:

protected void Page_PreInit(object sender, EventArgs e)
{
    // Create an event handler for the master page's PricesDoubled event
    Master.PricesDoubled += new EventHandler(Master_PricesDoubled);
}

有了此程式代碼,每當 DoublePrice 按兩下 [按鈕] 時,就會重新整理內容頁面中的 GridView。

圖 8 和 9 說明此行為。 圖 8 顯示第一次瀏覽時的頁面。 請注意,GridView(主版頁面左欄中)和 ProductsGrid GridView(在內容頁面中)的價格值RecentProducts。 圖 9 顯示按鍵之後 DoublePrice 的同一個畫面。 如您所見,新價格會立即反映在 GridViews 中。

初始價格值

圖 08:初始價格值(按兩下以檢視完整大小的影像

Just-Doubled 價格會顯示在 GridViews 中

圖 09:Just-Doubled 價格會顯示在 GridViews 中(按兩下以檢視完整大小的影像

摘要

在理想情況下,主版頁面及其內容頁面彼此完全分開,不需要任何層級的互動。 不過,如果您有主版頁面或內容頁面顯示可從主版頁面或內容頁面修改的數據,則您可能需要在修改數據時,讓主版頁面警示內容頁面(反之亦然),以便更新顯示。 在上一個教學課程中,我們已瞭解如何以程序設計方式與其主版頁面互動內容頁面;在本教學課程中,我們已探討如何讓主版頁面起始互動。

雖然內容與主版頁面之間的程式設計互動可能源自內容或主版頁面,但使用的互動模式取決於原點。 差異在於內容頁面具有單一主版頁面,但主版頁面可以有許多不同的內容頁面。 主版頁面與其直接與內容頁面互動,更好的方法是讓主版頁面引發事件,以表示已採取某些動作。 那些關心動作的內容頁面可以建立事件處理程式。

快樂的程序設計!

深入閱讀

如需本教學課程中所討論主題的詳細資訊,請參閱下列資源:

關於作者

斯科特·米切爾,多個 ASP/ASP.NET 書籍的作者,4GuysFromRolla.com 的創始人,自1998年以來一直與Microsoft Web 技術合作。 斯科特擔任獨立顧問、教練和作家。 他的最新書是 山姆斯在24小時內 ASP.NET 3.5。 斯科特可以透過 mitchell@4GuysFromRolla.com 他在的部落格聯繫到或通過他的博客 http://ScottOnWriting.NET

特別感謝

本教學課程系列已由許多實用的檢閱者檢閱。 本教學課程的主要檢閱者是 Suchi Banerjee。 有興趣檢閱我即將推出的 MSDN 文章嗎? 如果是,請將一行放在 mitchell@4GuysFromRolla.com