ModalPopupExtender
AjaxControlToolkit学习笔记之ModalPopupExtender
ModalPopupExtender控件学习笔记
ModalPopupExtender控件主要有两种使用方式:客户端使用方式和服务器端使用方式。这两种使用方式在ModalPopup的官方例子中都有介绍。
1、客户端使用方式
客户端使用方式又可以分为两种
A.直接设置OKControlID的方式
ModalPopupExtender控件在使用时必须要设置TargetControlID和PopupControlID这两个属性,我的理解是,对于ExtenderControl而言TargetControlID属性必须指定,否则就不知道在哪个DOM元素上附加客户端行为了。PopupControlID表示要弹出的仿模式窗口的DOM元素,常见的是Panel控件,这个如果不指定,也没有意义。有时,在执行上下文中可能要在确认这个模式窗口时,执行一些脚本,则可以设置OnOKScript属性,指明确认时要执行的脚本函数。
B.获取一个ModalPopupBehavior实例的方式。
如果页面上放置了ModalPopupExtender控件则可以用$find方法得到一个ModalPopupBehavior实例,这样就可以调用ModalPopupBehavior实例的任何方法了,如hide、show等,此时客户端的行为可以完全自己控制了。这种情况下ModalPopupExtender控件必须要设置BehaviorID属性,否则无法用$find方法来获取ModalPopupBehavior实例。
有时,我们会感觉直接调用ModalPopupBehavior实例的方法比较麻烦,可以给ModalPopupBehavior实例添加一些事件,以方便我们添加一些自定义控制,如下图,
我们在编辑一个文本框的内容时,在模式窗弹出之后,同时让CheckBox选中文本框中的值,这是需要一个OnAfterShown事件。有时在点击确认时,需要验证录入数据的正确性,需要一个OnBeforeOK事件,如果验证不能通过就取消提交。要实现这样的功能我们需要给ModalPopupExtender控件添加相应属性,我们以OnBeforeOK事件为例说明具体步骤:
第一步,给ModalPopupExtender控件添加OnBeforeOK属性
/// <summary>
/// 确认之前发生的事件
/// </summary>
[DefaultValue("")]
[ExtenderControlEvent]
[ClientPropertyName("beforeOK")]
public string OnBeforeOK
{
get { return GetPropertyValue("OnBeforeOK", string.Empty); }
set { SetPropertyValue("OnBeforeOK", value); }
}
这里要注意ExtenderControlEvent Attribute的使用。
第二步,给ModalPopupBehavior添加相应方法,来订阅、取消相应事件,及触发事件的方法。
add_beforeOK: function(handler) {
this.get_events().addHandler('beforeOK', handler);
},
remove_beforeOK: function(handler) {
this.get_events().removeHandler('beforeOK', handler);
},
raiseBeforeOK: function(eventArgs) {
var handler = this.get_events().getHandler('beforeOK');
if (handler) {
handler(this, eventArgs);
}
},
第三步,修改相应方法的代码,触发事件
_onOk: function(e) {
var element = $get(this._OkControlID);
if (element && !element.disabled) {
var eventArgs = new Sys.CancelEventArgs();
this.raiseBeforeOK(eventArgs);
if (!eventArgs.get_cancel()) {
if (this.hide() && this._OnOkScript) {
window.setTimeout(this._OnOkScript, 0);
}
e.preventDefault();
return false;
}
}
},
这里修改了_onOk方法,也可以根据情况修改其他方法。
第四步,使用ModalPopupExtender控件时,为OnBeforeOK属性赋值,此属性为一个脚本函数。这个函数中,我们可以执行args.set_cancel(true);从而阻止hide方法和OnOkScript脚本的执行。
客户端使用的方式可以任意发挥,OnOKScript属性挂接的函数完全可以使用Sys.Net.WebRequest发起异步请求,获取服务器端的信息。
2、服务器端使用方式
这种方式与传统的服务器控件的使用方式相同,就是直接调用ModalPopupExtender控件的Show()方法和Hide()方法来控制模式窗口的现实与隐藏,其实也是通过在客户端生成这样一句脚本来实现的:
(function() {
var fn = function() {
AjaxControlToolkit.ModalPopupBehavior.invokeViaServer('programmaticModalPopupBehavior', true);
Sys.Application.remove_load(fn);
};
Sys.Application.add_load(fn);
})();
在服务器端调用ModalPopupExtender控件的Show()方法或Hide()方法有个缺点,就是会引起回发,用户体验不好。我们可以将弹出的模式窗口(一个panel控件)放到一个UpdatePanel控件中,并将触发按钮注册为异步回发按钮来改善用户体验。一个常见的例子是GridView配合FormView或者 DetailView进行业务对象的修改,页面数据用GridView显示,修改时,用模式窗弹出一个FormView,修改完毕保存到数据库,并更新GridView(当然就地编辑的话,直接用UpdatePanel即可)。 具体实现步骤如下:
第一步:建立GridView
<asp:UpdatePanel UpdateMode="Conditional" ID="upXXXXX" runat="server">
<ContentTemplate>
<xx:XXGridView id="gvDDDDDD" runat="server" DataKeyNames="Id" AllowSorting="True" skinid="PagingGridView" DataSourceID="ods" EnableViewState="False">
<Columns>
<asp:BoundField DataField="CreatedDate" HeaderText="XXXXXX" SortExpression="CreatedTime" />
<asp:BoundField DataField="CreatedBy" HeaderText="CCCCCC" SortExpression="CreatedBy" />
<asp:BoundField DataField="Name" HeaderText="CCCCC" />
<asp:BoundField DataField="Comment" HeaderText="CCCCCC" />
<asp:TemplateField><ItemTemplate>
<asp:LinkButton id="btnEdit" runat="server" CommandName="Select" OnClick="btnEdit_Click">编辑</asp:LinkButton>
</ItemTemplate></asp:TemplateField>
<asp:CommandField ShowDeleteButton="True" DeleteText="删除" />
</Columns>
</xx:XXGridView>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnSave" />
<asp:AsyncPostBackTrigger ControlID="btnOK" />
</Triggers>
</asp:UpdatePanel>
<asp:ObjectDataSource id="ods" runat="server" EnablePaging="True"
TypeName="XXXXXX"
SelectMethod="GetPaged" SelectCountMethod="GetCount"
SortParameterName="sortExpression"
DeleteMethod="DeleteById">
<SelectParameters>
<huag:WhereClauseParameter Name="whereClause" QueryStringField="id" Type="String" DataField="XXId"></huag:WhereClauseParameter>
</SelectParameters>
</asp:ObjectDataSource>
第二步:建立弹出的层,仿模式窗口
<asp:Panel ID="pnlPopup" runat="server" CssClass="x-pne" Width="460px" style="display:none;">
<asp:UpdatePanel ID="updDetail" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Button id="btnShowPopup" runat="server" style="display:none" />
<ajaxToolKit:ModalPopupExtender ID="mdlPopup" runat="server"
BehaviorID="xxxEdit"
TargetControlID="btnShowPopup"
PopupControlID="pnlPopup"
CancelControlID="btnClose" BackgroundCssClass="modalBackground"
PopupDragHandleControlID="pnlDrag"
/>
<asp:Panel ID="pnlDrag" runat="server" CssClass="corner-bg x-pne-lt x-pne-left dragTitle">
<div class="corner-bg x-pne-rt x-pne-right">
<div class="corner-bg x-pne-t">
<div class="x-pne-btn" onclick="$find('xxxEdit').hide();"></div>
<div class="x-pne-caption font dragTitle"><span>标题</span></div>
</div>
</div>
</asp:Panel>
<div class="side-bg x-pne-l">
<div class="side-bg x-pne-r">
<div class="x-pne-c" style="width: 448px; height: 300px">
<div id="contentPanel" style="padding-left:10px;"><br />
这里是FormView的内容,完全可以使用一个FormView控件,这里没有给出
<table width="100%">
<tr>
<td style="width: 100px">内容1</td><td><asp:TextBox ID="txtEdit1" runat="server" CssClass="textField text-bg border-blur" Width="90%"></asp:TextBox></td>
</tr>
<tr>
<td style="width: 100px">内容2</td><td><asp:TextBox ID="txtEdit2" runat="server" CssClass="text-bg border-blur" TextMode="MultiLine" Rows="14" Width="92%"></asp:TextBox></td>
</tr>
<tr >
<td colspan="2" align="center" style="padding-top:10px;">
<table width="60%" >
<tr align="center">
<td>
<div class="btn-side btn-bg"></div>
<div class="btn-body btn-bg" style="background-position: 0px 168px; width: 66px"><asp:Button ID="btnOK" runat="server" Text=" 确定 " CssClass="font" OnClick="btnOK_Click" /></div>
<div class="btn-side btn-bg" style="background-position: 0px 189px"></div>
</td>
<td>
<div class="btn-side btn-bg"></div>
<div class="btn-body btn-bg" style="background-position: 0px 168px; width: 66px"><asp:Button ID="btnClose" runat="server" Text=" 取消 " CssClass="font" /></div>
<div class="btn-side btn-bg" style="background-position: 0px 189px"></div>
</td>
</tr>
</table>
</td>
</tr>
</table>
<br />
</div>
</div>
</div>
</div>
<div class="corner-bg x-pne-lb x-pne-left">
<div class="corner-bg x-pne-rb x-pne-right">
<div class="corner-bg x-pne-b"></div>
</div>
</div>
</ContentTemplate>
</asp:UpdatePanel>
</asp:Panel>
每一个ExtenderControl都需要挂靠一个Dom元素,<asp:Button id="btnShowPopup" runat="server" style="display:none" />就是起这个作用,其本身没有意义,所以这里要隐藏之。
第三步:写编辑按钮的代码btnEdit_Click,弹出模式窗口
// 得到GridView当前行的信息,更新FormView上相应控件的值,或者FormView.databind。
。。。。。。其他语句
updPnlDetail.Update();
mdlPopup.Show();
第四步:弹出窗口编辑完成保持时的代码 btnOK
// 保存修改,更新到数据库
gvDDDD.DataBind();// 同时更新到界面。