AJAX ModalPopup Extender in GridView Control

在 ASP.NET 3.5 中,你可以使用 UpdatePanel 及 ScriptManager 伺服器控制項來更新局部的網頁,而不需重新載入整個網頁。當你使用 GridView 控制項搭配 UpdatePanel 控制項,對資料來源進行編輯、刪除等功能,及重新繫結資料更新頁面的記錄,就可以透過觸發 UpdatePanel 控制項來完成。

你可以啟用 GridView 控制項內建的編輯功能,讓使用者能夠編輯個別資料列的內容。但如果需要編輯的資料欄位或是內容不足以在有限的方格(Grid)中呈現時,就必須考慮其他編輯模式。這時,你可以考慮搭配 DetailsView 控制項,或是採用更進階的巢狀式應用等。不過,在這裡要介紹另一種呈現方式,就是選用 ModalPopupExtender 控制項,以強制回應的快顯對話方塊來編輯資料列的內容。本文接下來的主題將帶你瞭解如何把 ModalPopupExtender 控制項整合應用到 GridView 控制項。ModalPopupExtender 控制項是 AJAX Control Toolkit 所提供的擴充性控制項。你可以造訪這裡下載 AJAX Control Toolkit。

本範例會從 AdventureWorks 範例資料庫,使用 GridView 控制項搭配使用 FormView 控制項,建立員工資訊的主要及詳細頁面。你可以從這裡下載範例資料庫。

定義 GridView 的內容
首先,你需定義一個包含 GridView 控制項的更新面板:
<asp:UpdatePanel ID="EmployeesUpdatePanel" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:GridView ID="EmployeesGridView" runat="server" DataKeyNames="EmployeeID"
DataSourceID="EmployeesSqlDataSource" AutoGenerateColumns="False" AllowPaging="True">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="First Name"
SortExpression="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="Last Name"
SortExpression="LastName" />
<asp:BoundField DataField="NationalIDNumber" HeaderText="ID Number"
SortExpression="NationalIDNumber" />
<asp:BoundField DataField="Gender" HeaderText="Gender"
SortExpression="Gender" ItemStyle-HorizontalAlign="Center" />
<asp:BoundField DataField="BirthDate" HeaderText="Birth Date"
SortExpression="BirthDate" DataFormatString="{0:yyyy/MM/dd}" />
<asp:BoundField DataField="MaritalStatus" HeaderText="Marital Status"
SortExpression="MaritalStatus" ItemStyle-HorizontalAlign="Center" />
<asp:TemplateField>
<ItemTemplate>
<a href="javascript:showModalPopup(<%# Eval("EmployeeID")%>);">Edit</a>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>

上例中,在 GridView 控制項的資料行中加入樣板欄位,並在其 ItemTemplate 標籤中,加入一個編輯連結用來呼叫 JavaScript 函式,以顯示快顯對話方塊。


定義快顯對話方塊的內容
接下來,就是定義包含強制回應快顯對話方塊內容的面板:
<asp:Panel id="ModalPopupPanel" runat="server" Style="display: none" CssClass="modalPopup">
<asp:UpdatePanel ID="ModalPopupUpdatePanel" runat="server" UpdateMode="Conditional"
ChildrenAsTriggers="False">
<ContentTemplate>
<asp:UpdateProgress ID="ModalPopupUpdateProgress" runat="server"
AssociatedUpdatePanelID="ModalPopupUpdatePanel">
<ProgressTemplate>
<div>Loading ...</div>
</ProgressTemplate>
</asp:UpdateProgress>
<asp:FormView ID="EmployeeFormView" runat="server" DefaultMode="Edit"
DataKeyNames="EmployeeID" DataSourceID="EmployeeDetailsSqlDataSource"
OnItemUpdated="EmployeeFormView_ItemUpdated">
<EditItemTemplate>
<table>
<tr>
<td>First Name:</td>
<td>
<asp:Label ID="FirstNameLabel" runat="server"
Text='<%# Eval("FirstName") %>' />
</td>
</tr>
<tr>
<td>Last Name:</td>
<td>
<asp:Label ID="LastNameLabel" runat="server"
Text='<%# Eval("LastName") %>' />
</td>
</tr>
<tr>
<td>ID Number:</td>
<td>
<asp:TextBox ID="NationalIDNumberTextBox" runat="server"
Text='<%# Bind("NationalIDNumber") %>' />
</td>
</tr>
<tr>
<td>Gender:</td>
<td>
<asp:DropDownList ID="GenderDropDownList" runat="server"
SelectedValue='<%# Bind("Gender") %>'>
<asp:ListItem Value="M">Male</asp:ListItem>
<asp:ListItem Value="F">Female</asp:ListItem>
</asp:DropDownList>
</td>
</tr>
<tr>
<td>Birth Date:</td>
<td>
<asp:TextBox ID="BirthDateTextBox" runat="server"
Text='<%# Bind("BirthDate","{0:yyyy/MM/dd}") %>' />
</td>
</tr>
<tr>
<td>Marital Status:</td>
<td>
<asp:DropDownList ID="MaritalStatusDropDownList" runat="server"
SelectedValue='<%# Bind("MaritalStatus") %>'>
<asp:ListItem Value="M">Married</asp:ListItem>
<asp:ListItem Value="S">Single</asp:ListItem>
</asp:DropDownList>
</td>
</tr>
</table>
<asp:Button ID="HiddenUpdateButton" runat="server" CommandName="Update"
style="display: none" />
</EditItemTemplate>
</asp:FormView>
<asp:HiddenField ID="EmployeeIDHiddenField" runat="server"
OnValueChanged="EmployeeIDHiddenField_ValueChanged" />
<asp:Label ID="UpdatePanelMessage" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
<div style="text-align: center">
<asp:Button id="OkButton" runat="server" Text="確 定" CommandName="Update"></asp:Button>
<asp:Button id="CancelButton" runat="server" Text="取 消"></asp:Button>
</div>
</asp:Panel>

在面板中,我們加入了包含 FormView 控制項的 UpdatePanel 控制項,並在 FormView 控制項的編輯樣板中,加入隱藏的更新按鈕,這個按鈕將會透過 JavaScript 觸發 UpdatePanel 控制項的更新動作,並透過 FormView 控制項所搭配的 SqlDataSource 控制項來執行員工資料的更新。因為在 ModalPopupUpdatePanel 更新面板中的 ChildrenAsTriggers 屬性被設為 False,所以必須明確呼叫 Update 方法,才能更新面板的內容:
protected void EmployeeFormView_ItemUpdated(object sender, EventArgs e)
{
EmployeesGridView.DataBind();
EmployeesUpdatePanel.Update();
}

而 OkButton 及 CancelButton 按鈕則分別用來定義快顯對話盒中,「確定」及「取消」動作的目標控制項。另外,在 UpdatePanel 控制項中的還加入了隱藏欄位 EmployeeIDHiddenField,用來記錄在 GridView 控制項中被選取員工的主索引鍵值,並加入其 ValueChanged 事件的處理常式:
protected void EmployeeIDHiddenField_ValueChanged(object sender, EventArgs e)
{
ModalPopupUpdatePanel.Update();
}

這個隱藏欄位將透過 JavaScript 來觸發 UpdatePanel 控制項,以載入 FormView 控制項的繫結資料。

加入 ModalPopupExtender 控制項
<asp:Button runat="server" ID="HiddenTargetControlForModalPopup" style="display:none" />
<ajaxToolkit:ModalPopupExtender ID="ModalPopupExtender1" runat="server"
TargetControlID="HiddenTargetControlForModalPopup"
PopupControlID="ModalPopupPanel"
BackgroundCssClass="modalBackground"
DropShadow="true"
OnOkScript="onOk()"
OkControlID="OkButton"
CancelControlID="CancelButton"
/>

加入用戶端程式碼
<script type="text/javascript" language="javascript">
<!--
function onOk() {
__doPostBack('<%= string.Format("{0}$HiddenUpdateButton", EmployeeFormView.UniqueID) %>','');
}

function showModalPopup(v)
{
var modalPopupBehavior = $find('<%= ModalPopupExtender1.ClientID %>');
modalPopupBehavior.show();
var hiddenField = $get('<%= EmployeeIDHiddenField.ClientID %>');
if (hiddenField) {
hiddenField.value = v;
__doPostBack('<%= EmployeeIDHiddenField.UniqueID %>','');
}
}
//-->
</script>

上例中,你會發現在程式碼是使用 $find 函式來取得 ModalPopup 行為類別(Behavior)執行個體的參照。這與 $get 函式又有什麼不同呢?在 Microsoft Ajax Library 中,$get 函式是 Sys.UI.DomElement.getElementById 方法的別名,用來取得 DOM 元素的參照;而 $find 函式則是 Sys.Application.findComponent 方法的別名,它會傳回 Ajax Client Component 執行個體的參照。因為 ModalPopup 亦是 Sys.Component,所以你必須使用 $find 函式才能取得 ModalPopup Behavior 執行個體的參照。但為何又稱 ModalPopup 是行為類別呢?那是因為 ModalPopup 是繼承自 Sys.UI.Behavior 類別的 Component。想瞭解更多有關於 ASP.NET AJAX Client 的相關資訊,可以參考這裡


 Download source code - 430 KB


Share/Save/Bookmark

5 comments :: AJAX ModalPopup Extender in GridView Control

  1. hello,楼主!
    我不太明白HiddenTargetControlForModalPopup是ModalPopupExtender1的TargetControlID 那是如何触发的
    按你文章说的做了 点击edit后ModalPopupPanel呈现出来后马上关闭 不知道为何?
    希望等到你的回复 richiezheng@evershinecpa.com

  2. AJAX ModalPopup Extender in GridView Control 's source code download error!
    望发一份source code至richiezheng@evershinecpa.com 万分谢谢!

  3. 我已經把原始碼寄到你指定的信箱了。

  4. 關於你的提問說明如下:
    ModalPopupExtender 的 TargetControlID 屬性是用來觸發顯示快顯視窗的目標控制項。換句話說,我們通常會提供一個 Button 控制項,來做為開啟顯示快顯視窗的觸發按鈕。然而,在這裡並不是使用 Button 控制項,取而代之的是在 GridView 的 ItemTemplate 中呼叫 JavaScript 函式 showModalPopup 來顯示快顯視窗。可是,ModalPopupExtender 無論如何都必須指定 TargetControlID 屬性,否則將會引發錯誤。因此,在這裡才會指定一個隱藏的按鈕。

  5. excellent

張貼留言