65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET AJAX 控件工具包 ModalPopupExtender 控件实战

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.85/5 (160投票s)

2009年4月4日

CPOL

13分钟阅读

viewsIcon

1386412

downloadIcon

64829

演示了如何在各种场景中使用 AjaxControlToolkit 的 ModalPopupExtender 控件显示模态弹出窗口,以实现流畅的用户交互。

目录

开发平台

  • Visual Studio 2008 SP1
  • Microsoft .NET Framework 3.5 SP1
  • ASP.NET Ajax 3.5 SP1
  • ASP.NET Ajax 控件工具包 for 3.5 SP1
  • IIS 5.1~7
图:费用列表演示应用程序。

引言

ASP.NET Ajax 控件工具包是 ASP.NET 社区的一项很棒的贡献,它配备了许多良好且实用的控件扩展器。在本文中,我们将探讨 Ajax 控件工具包中的模态弹出对话框扩展器控件。我们将了解模态弹出控件在 ASP.NET 富客户端和通用 Web 应用程序中可以成为有用工具的各种场景。我们还将介绍有关模态弹出扩展器控件的一些技巧和故障排除。首先,我们将介绍什么是模态弹出扩展器以及如何使用它。

显示模态弹出窗口

让我们通过一个简单的“Hello World”模态弹出开始我们的旅程。在本节中,我们将了解如何使用模态弹出扩展器控件来显示模态弹出窗口。学习任何新技术最好的方法就是通过示例。因此,让我们先写一个小的示例代码,然后我们将分析代码的含义和工作原理。

<asp:scriptmanager id="ScriptManager1" runat="server">
</asp:scriptmanager>

<asp:button id="Button1" runat="server" text="Button" />

<cc1:modalpopupextender id="ModalPopupExtender1" runat="server" 
	cancelcontrolid="btnCancel" okcontrolid="btnOkay" 
	targetcontrolid="Button1" popupcontrolid="Panel1" 
	popupdraghandlecontrolid="PopupHeader" drag="true" 
	backgroundcssclass="ModalPopupBG">
</cc1:modalpopupextender>

<asp:panel id="Panel1" style="display: none" runat="server">
	<div class="HellowWorldPopup">
                <div class="PopupHeader" id="PopupHeader">Header</div>
                <div class="PopupBody">
                    <p>This is a simple modal dialog</p>
                </div>
                <div class="Controls">
                    <input id="btnOkay" type="button" value="Done" />
                    <input id="btnCancel" type="button" value="Cancel" />
		</div>
        </div>
</asp:panel>

上面的代码不言自明,但我们仍将一步一步地讨论它。

步骤 1

扩展器控件的引擎是 ASP.NET Ajax 3.5 的 Script Manager。只要我们想使用任何扩展器控件,就必须在页面上下文中声明它。因此,请从工具箱中拖放 ScriptManager,或编写 Script Manager 的标签。

第二步

现在,在页面中添加一个您想显示为模态对话框的 Div 或 ASP.NET 面板。为面板指定一个 id,并在面板中放置完成和取消按钮。添加一个标题 div 到面板中,它将作为弹出窗口的标题。最后,在页面上的任何位置(除了您想显示为模态弹出窗口的 div 内部)添加一个目标链接或按钮。单击该链接将显示弹出窗口。

步骤 3

现在,在页面中添加一个模态弹出扩展器控件,并将 TargetControlID 属性设置为用户单击以显示模态的按钮的 id。将 PopupControlID 属性设置为您想显示为模态的 ASP 面板的 id。最后,将 CancelControlID 属性设置为“btnCancel”,将 OkControlID 属性设置为“btnOkay”。

步骤 4

一切就绪,是时候添加一些样式了,以便在显示模态窗口时获得灯箱效果。下面的两个样式仅用于演示目的。但重要的是,如果我们想为页面添加透明度/灯箱效果,我们就必须设置模态弹出扩展器的 CSS。要实现此效果,我们会添加背景颜色,然后应用滤镜和不透明度 CSS 属性。然后,我们必须为弹出对话框添加样式。全部完成。现在,单击目标按钮,一个模态弹出窗口将会弹出。

.ModalPopupBG
{
    background-color: #666699;
    filter: alpha(opacity=50);
    opacity: 0.7;
}

.HellowWorldPopup
{
    min-width:200px;
    min-height:150px;
    background:white;
}

通过脚本关闭和打开模态弹出窗口

在开发应用程序时,我们可能需要通过 JavaScript 显示模态弹出窗口,这可能需要我们动态地使用 JavaScript 打开和关闭弹出窗口。例如,一个警告消息,只显示 2 秒钟,然后自动关闭。有一些技巧可以做到这一点。我们将讨论其中的大多数。首先,让我们讨论如何在不单击按钮或链接的情况下打开模态弹出窗口。假设我们已经在页面上设置了一个模态弹出窗口,并且在页面加载时需要显示一个警告消息。首先,我们必须使用 style="display:none" 隐藏模态弹出窗口的目标控件 ID 和控件按钮。然后,我们需要为模态弹出扩展器控件添加 BehaviorID 属性。现在,定义一个在 pageLoad 上执行我们技巧的脚本。PageLoad 是 Script Manager 在客户端页面加载时自动调用的一个函数。在 page load 中,我们将添加代码来显示模态窗口,并在一段时间后再次隐藏弹出窗口。

要显示弹出窗口,我们将使用 $find('behaviourIDofModal').show();,要隐藏模态窗口,我们将使用 $fin('behaviourIDofTheModal').hide();。或者,我们可以使用 JavaScript 自动触发 targetcontrolid 的单击 JavaScript 事件来显示弹出窗口,并触发弹出窗口的取消控件的单击事件来再次隐藏弹出窗口。

<script language="javascript" type="text/javascript">
    function pageLoad() {
        ShowPopup();
        setTimeout(HidePopup, 2000);
    }

    function ShowPopup() {
        $find('modalpopup').show();
        //$get('Button1').click();
    }

    function HidePopup() {
        $find('modalpopup').hide();
        //$get('btnCancel').click();
    }
</script>

在模态弹出窗口中显示 iframe

在本节中,我们将了解如何在模态弹出窗口中使用 iframe,并讨论一些在模态弹出窗口中使用 iframe 的有用场景。让我们从一个简单的例子开始。在此示例中,我们将使用一个模态弹出窗口,该窗口将用作添加新费用项目的 3 步向导控件。向导将是一个单独的页面,我们在其中将三个步骤放在 multiview ASP.NET 控件旁边。在第一步中,我们将显示客户端的输入面板,用户保存数据后,我们将显示一个简单的成功消息或错误消息。如果数据保存成功,模态窗口将在显示成功消息后关闭;如果发生错误,我们将显示错误消息并将其带回到第一步。我们还将使用单独的 aspx 页面实现整个向导,并在模态弹出窗口中使用 iframe 显示此页面。

在本节中,我们遇到几个问题。首先是模态窗口的确定和取消按钮。由于向导的确定和取消按钮是 iframe 模态弹出窗口内的向导的一部分,因此扩展器在第一次加载扩展器时将无法找到它们。因此,我们必须在 iframe 外部添加确定和取消控件,然后隐藏这些控件。在后面的部分,我们将看到如何处理 iframe 源页面的确定和取消。

宿主页面的代码
<asp:button id="btnAddNew" runat="server" text="New Expanse" />

<cc1:modalpopupextender id="ModalPopupExtender1" 
	runat="server" cancelcontrolid="btnCancel" 
	okcontrolid="btnOkay" targetcontrolid="btnAddNew" 
	popupcontrolid="Panel1" popupdraghandlecontrolid="PopupHeader" 
	drag="true" backgroundcssclass="ModalPopupBG">
</cc1:modalpopupextender>

<div class="popupConfirmation" id="Panel1" style="display: none">
    <iframe id="frameeditexpanse" src="EditExpanse.aspx" frameborder="0">
    </iframe>
    <div class="popup_Buttons" style="display: none">
        <input id="btnOkay" type="button" value="Done" />
        <input id="btnCancel" type="button" value="Cancel" />
    </div>
</div>
源页面的代码
<form id="form1" runat="server">
    <div class="popup_Container">
        <div class="popup_Titlebar" id="PopupHeader">
            <div class="TitlebarLeft">
                Edit Expanse
            </div>
            <div class="TitlebarRight" onclick="cancel();">
            </div>
        </div>
        <div class="popup_Body">
            <%--The content will go here--%>
        </div>
        <div class="popup_Buttons">
            <input id="btnOkay" type="button" value="Done" runat="server" />
            <input id="btnCancel" onclick="cancel();" type="button" value="Cancel" />
        </div>
    </div>
</form>

从 iframe 关闭弹出窗口

我们已经看到了如何在模态弹出窗口中显示框架内容。在本节中,我们将了解如何从 iframe 源页面关闭模态弹出窗口。正如我们在上面的源代码中所看到的,我们两次放置了我们的确定和取消控件。在宿主页面中定义的确定和取消按钮是为了弹出窗口扩展器,以便我们可以引用这些按钮到模态弹出窗口扩展器,这将使我们免于任何运行时错误。我们在 iframe 的源页面中也有两个确定和取消按钮,它们将由用户用于确定和取消对话框。宿主页面的按钮对用户是隐藏的。

在模态弹出窗口中,如果我们把确定和取消按钮放在 iframe 外面,如果我们点击其中任何一个按钮,模态窗口都会关闭,无论我们在模态窗口内是否完成了工作。代码如下。

iframe 源页面代码后端的 C# 代码
protected void btnOkay_Click(object sender, EventArgs e)
{
    try
    {
       // code will go here
        MultiViewExpanse.ActiveViewIndex = 1;
        ClientScript.RegisterStartupScript(this.GetType(), 
		"onload", "onSuccess();", true);
    }
    catch
    {
        ClientScript.RegisterStartupScript(this.GetType(), 
		"onload", "onError();", true);
        MultiViewExpanse.ActiveViewIndex = 1;
    }
}
iframe 源页面 HTML 中的 JavaScript 代码
<script language="javascript" type="text/javascript">
    function getbacktostepone() {
        window.location = "EditExpanse.aspx";
    }
    function onSuccess() {
        setTimeout(okay, 2000);
    }
    function onError() {
        setTimeout(getbacktostepone, 2000);
    }
    function okay() {
        window.parent.document.getElementById('btnOkay').click();
    }
    function cancel() {
        window.parent.document.getElementById('btnCancel').click();
    }
</script>

当用户单击向导中的确定按钮时,我们执行一些操作,然后触发宿主页面的确定或取消按钮的单击事件来关闭对话框。

同一源在 iframe 中的不同数据

在前面的示例中,我们已经看到了如何在模态弹出窗口中显示框架内容。在本节中,我们将讨论在模态弹出窗口中显示框架内容的自定义版本。在我们费用列表的示例中,网格项中有一个编辑按钮。假设我们不想要就地编辑,当用户单击编辑按钮时,一个模态窗口将弹出并显示相关数据。有许多方法可以实现此要求。但现在,我们将使用模态窗口中的 iframe 并更改 iframe 的源,并向 src 属性添加适当的查询字符串,以显示它在模态窗口中显示相关数据。

rowdataboundevent 中,我们修改了编辑按钮的属性以显示模态窗口。像这样配置 modalpopupextender,使其目标控件 ID 不显示。当用户单击任何项上的编辑按钮时,会调用一个客户端 JavaScript 函数,并传递费用 ID 作为参数。现在,我们要做的就是设置 iframe 的 src 属性,然后使用客户端 JavaScript 显示弹出窗口。下面的完整代码提供了更好的理解。

RowDataBound 事件中的代码
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        Expanse expanse = e.Row.DataItem as Expanse;
        (e.Row.FindControl("lnkEdit") as LinkButton).Attributes.Add
		("onClick", "ShowEditModal('" + expanse.ID + "');");
        (e.Row.FindControl("lnkDelete") as LinkButton).CommandArgument = 
						expanse.ID.ToString();
    }
}
模态弹出窗口的代码
<asp:button id="ButtonEdit" style="display: none" runat="server" text="Edit Expanse" />

<cc1:modalpopupextender id="ModalPopupExtender2" runat="server"
	cancelcontrolid="ButtonEditCancel" okcontrolid="ButtonEditDone"
	targetcontrolid="ButtonEdit" popupcontrolid="DivEditWindow"
	backgroundcssclass="ModalPopupBG" oncancelscript="EditCancelScript();"
	onokscript="EditOkayScript();" behaviorid="EditModalPopup">
</cc1:modalpopupextender>

<div class="popup_Buttons" style="display: none">
    <input id="ButtonEditDone" type="button" value="Done" />
    <input id="ButtonEditCancel" type="button" value="Cancel" />
</div>
<div class="popupConfirmation" id="DivEditWindow" style="display: none">
    <iframe id="IframeEdit" frameborder="0" scrolling="no" height="203">
    </iframe>
</div>
JavaScript 中的代码
<script language="javascript" type="text/javascript">
    function ShowEditModal(ExpanseID) {
        var frame = $get('IframeEdit');
        frame.src = "EditExpanse.aspx?UIMODE=EDIT&EID=" + ExpanseID;
        $find('EditModalPopup').show();
    }
    function EditCancelScript() {
        var frame = $get('IframeEdit');
        frame.src = "DemoLoading.aspx";
    }
    function EditOkayScript() {
        RefreshDataGrid();
        EditCancelScript();
    }
    function RefreshDataGrid() {
        $get('btnSearch').click();
    }
</script>

我们可以做一些技巧来使一个编辑窗口到另一个编辑窗口的页面事务处理得更好。我们将 iframe 的源保留为一个显示“加载中”的演示页面。当用户单击“加载中”并调用 ShowEditModal 时,在该函数中,我们将设置适当的 src 来加载适当的内容。当用户单击确定或取消时,我们将再次将源重置为演示页面。上面代码列表中的脚本演示了相同的想法。

ModalPopupExtender 内的 Update Panel

Update Panel 是我们在 Web 应用程序中使用 ASP.NET Ajax 时最简单、最友好的控件。在本节中,我们将了解一些关于模态弹出扩展器内 Update Panel 的技巧。如果我们想让框架内容更好,我们可以在源页面中使用 Update Panel 和其他客户端功能。但在这种情况下,我们必须确保 HTTP Cache 被正确刷新。只需将以下代码放入 page load 中即可避免不必要的页面 cache。但您也可能想保留 cache;在这种情况下,请正确使用 HTTP cache

Response.Cache.SetCacheability(HttpCacheability.NoCache);

现在,让我们谈谈带有 Update Panel 的普通模态弹出窗口。如果我们在 Update Panel 中有一个向导,完成工作后,我们可能想将向导重置到第一步,以便当用户单击“开始向导”时,向导从头开始。在这种情况下,使用一个隐藏的输入按钮,它将充当更新 Update Panel 的客户端触发器。在按钮的单击事件中,重新初始化向导。最后,在 onokayscriptoncancelscript 中添加必要的单击脚本以触发按钮的单击事件来运行进程。因此,当用户完成或经过几个步骤然后取消向导时,他将能够在单击“开始向导”后从头开始。

Modal Popup 内验证控件提示器的问题

在本节中,我们将展示另一个问题和模态弹出窗口的故障排除。这与验证控件和 validatorcalloutextender 有关。当我们在模态弹出窗口内有一个输入面板时,我们可能需要包含一些必需字段,或正则表达式验证器以及验证器提示器。正如你们可能已经猜到的,ASP.NET 验证器和验证器提示器在模态弹出扩展器内无法正常工作。当用户在模态弹出窗口内的输入面板中输入数据并单击确定以完成操作时,我们可能想要获取输入并执行一些操作,并最终清除输入面板以供新面板使用。当用户单击显示模态弹出窗口时,即使用户没有进行任何操作,validatorcalloutextender 也会弹出。有一个简单的解决方法,我们必须使用它。下面是完整的代码列表。

<asp:button id="Button1" runat="server" text="Click here to show the modal" 
	causesvalidation="false" />

<cc1:modalpopupextender id="ModalPopupExtender1" runat="server"
	cancelcontrolid="btnCancel" targetcontrolid="Button1"
	popupcontrolid="Panel1" popupdraghandlecontrolid="PopupHeader"
	drag="true" backgroundcssclass="ModalPopupBG" oncancelscript="ClearUI();"
	behaviorid="modalwithinput">
</cc1:modalpopupextender>

请注意,在上面的代码中,我们将目标控件的 CausesValidation 属性设置为 false。这是必要的,否则当我们单击按钮时,弹出窗口将启动,并且验证器提示器已经弹出,并且位置不正确,如下图所示。

图:验证器提示器显示错位。

下面是用于弹出窗口正文的代码,我们在其中添加了 ValidatorCalloutExtender。这里我们必须将 RequiredFieldValidatorDisplay 属性设置为 None,否则将显示必需字段验证器和验证器提示器的消息。

<div class="popup_Body">
    <p>Enter you name:
        <asp:textbox id="TextBox1" runat="server"></asp:textbox>
        <asp:requiredfieldvalidator id="RequiredFieldValidator1" runat="server"
		controltovalidate="TextBox1" errormessage="Please Enter your name"
		setfocusonerror="true" display="None"></asp:requiredfieldvalidator>
        <cc1:validatorcalloutextender id=
		"RequiredFieldValidator1_ValidatorCalloutExtender"
		runat="server" targetcontrolid="RequiredFieldValidator1"
		behaviorid="textValidator" enabled="True">
	</cc1:validatorcalloutextender>
    </p>
</div>

实际起作用的主要脚本如下。您可能会注意到,我们在 modalpopupextender 中没有提及任何 okaycontrolidonokayscript,而是在确定按钮的 onclientclick 属性中包含了一个客户端脚本。在确定按钮单击时,我们会验证输入是否确实有效,然后如果输入有效,我们会手动关闭弹出窗口,否则保持弹出窗口打开,并且如果输入无效,验证器提示器会自动弹出。接下来,当输入有效或用户单击取消时,我们会清除输入以供下次使用。请注意,我们在 clearUI() 函数中手动隐藏了 validatorcallout

<script language="javascript" type="text/javascript">
    function ClearUI() {
        $find("textValidator").hide();
        $get("TextBox1").value = "";
    }
    function IsValid() {
        var textbox = $get("TextBox1");
        if (textbox.value == "") {
            return false;
        }
        else
            return true;
    }
    function ClosePopup() {
        if (IsValid()) {
            $find('modalwithinput').hide();
            alert("You have given your name");
            ClearUI();
        }
    }
</script>

将模态弹出窗口用作交互确认对话框

我们为 Web 开发的大多数应用程序在某些区域都会在一定程度上使用某种形式的确定和取消对话框,尤其是在我们要删除数据或对数据进行重要修改时。通常,我们使用 window.alert()window.confirm 来显示此类消息,以获取用户确认并根据用户确认对话框的结果执行操作。ASP.NET Ajax 控件工具包有一个名为 ConfirmButtonExtender 的扩展器控件,它也可以用于显示自定义模态弹出窗口而不是 window.confirm,尤其用于确认对话框。

让我们设想一个场景,用户想通过单击删除按钮来删除网格中的一个费用项。用户必须被告知她/他将要删除他的一项费用。我们将显示一个模态对话框,在其中询问用户她/他是否真的打算删除。下面的完整代码列表可以更好地演示这个想法。

图:ConfirmButtonExtender 与模态弹出窗口。

下面是一个简单的代码,用于演示 ConfirmButtonExtender 与模态弹出窗口的想法。

<asp:templatefield showheader="False">
    <itemtemplate>
        <asp:linkbutton id="lnkDelete" runat="server" text="Delete" 
		causesvalidation="false" commandname="Delete" commandargument="ID">
		</asp:linkbutton><cc1:modalpopupextender 
		id="lnkDelete_ModalPopupExtender" runat="server" 
		cancelcontrolid="ButtonDeleteCancel" okcontrolid="ButtonDeleleOkay" 
		targetcontrolid="lnkDelete" popupcontrolid="DivDeleteConfirmation" 
		backgroundcssclass="ModalPopupBG">
        </cc1:modalpopupextender>
        <cc1:confirmbuttonextender id="lnkDelete_ConfirmButtonExtender" 
		runat="server" targetcontrolid="lnkDelete" enabled="True" 
		displaymodalpopupid="lnkDelete_ModalPopupExtender">
        </cc1:confirmbuttonextender>
    </itemtemplate>
    <itemstyle horizontalalign="Center" />
</asp:templatefield>

用于显示为确认窗口的模态弹出窗口的代码。

<asp:panel class="popupConfirmation" id="DivDeleteConfirmation" 
	style="display: none" runat="server">
    <div class="popup_Container">
        <div class="popup_Titlebar" id="PopupHeader">
            <div class="TitlebarLeft">
                Delete Expanse</div>
            <div class="TitlebarRight" onclick="$get('ButtonDeleteCancel').click();">
            </div>
        </div>
        <div class="popup_Body">
            <p>
                Are you sure, you want to delete the expanse?
            </p>
        </div>
        <div class="popup_Buttons">
            <input id="ButtonDeleleOkay" type="button" value="Okay" />
            <input id="ButtonDeleteCancel" type="button" value="Cancel" />
        </div>
    </div>
</asp:panel>

摘要

在本文中,我们看到了 ASP.NET Ajax 控件工具包的模态弹出扩展器控件的一些使用场景。我们还学习了关于模态弹出扩展器的一些技巧和窍门。还有许多其他有趣的场景有待探索,也有许多其他领域可以应用此模态弹出窗口。如果您觉得文章的任何部分不清楚,请留言。我很乐意进一步解释并解决用户在添加模态窗口时可能遇到的任何困难。最后,如果您喜欢这篇文章,请投票。

参考文献

历史

  • 2009年4月2日:初始版本
© . All rights reserved.