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

从模态弹出窗口返回一个值

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.81/5 (11投票s)

2011年2月28日

CPOL

2分钟阅读

viewsIcon

94878

downloadIcon

3271

如何从模态弹出窗口返回值。

引言

你可能在 Facebook 上见过,当你点击 添加好友 时,会弹出一个窗口

当你点击 发送请求 后,添加好友 按钮会变成 请求已发送。在不刷新页面的情况下,我们如何在 .NET 中实现这个功能?

剖析

我们将弹出窗口放在一个用户控件中。

用户控件

这是一个模态弹出窗口,包含我们想要处理的任何业务逻辑。为了演示,让弹出窗口显示一个日历,并将选定的日期返回到源页面的文本框中。

<%@ Control Language="C#" 
     AutoEventWireup="true" CodeFile="CalendarControl.ascx.cs"
     Inherits="CalendarControl" %>
<%@ Register Assembly="AjaxControlToolkit" 
             Namespace="AjaxControlToolkit" TagPrefix="asp" %>
<link href="Styles/Control.css" rel="stylesheet" type="text/css" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
    <ContentTemplate>
        <asp:Panel ID="Panel1" runat="server" 
                   BackColor="White" Style="display: none">
            <asp:Calendar ID="Calendar1" runat="server" 
                OnSelectionChanged="Calendar1_SelectionChanged"
                OnVisibleMonthChanged="Calendar1_VisibleMonthChanged"></asp:Calendar>
            <asp:ImageButton ID="btnClose" runat="server" 
                ImageUrl="~/Images/fancy_close.png"
                class="fancybox-close" OnClick="btnCloseMsg_Click" />
        </asp:Panel>
        <asp:ModalPopupExtender ID="Panel1_ModalPopupExtender" 
            runat="server" BackgroundCssClass="overlay_style"
            DropShadow="true" DynamicServicePath="" 
            Enabled="True" PopupControlID="Panel1"
            TargetControlID="FakeButton">
        </asp:ModalPopupExtender>
        <asp:Button ID="FakeButton" runat="server" Style="display: none" />
    </ContentTemplate>
</asp:UpdatePanel>

源页面

只需要一个文本框,用于接收结果,和一个按钮来显示弹出窗口。

SourcePage.jpg

<head runat="server">
    <title>Test</title>
</head>
<body>
    <form runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <asp:UpdatePanel ID="UpdatePanel1" runat="server">
        <ContentTemplate>
            <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
            <asp:Button ID="btnGetDate" runat="server" 
                 Text="Get Date" OnClick="btnGetDate_Click" />
            <uc1:CalendarControl ID="ucCalendar" 
                 runat="server" OnDateSelected="OnDateSelected" />
        </ContentTemplate>
    </asp:UpdatePanel>
    </form>
</body>
</html>

请注意,文本框包含在 UpdatePanel 中。

问题

主要问题是:如何让调用页面**感知**你的自定义控件? 也就是说,我们的控件是一个日历,我们希望源页面中的文本框**看到**我们刚刚选择的日期。

我发现了以下解决方案

  1. ASP 服务器端 JavaScript 风格的日历弹出窗口
  2. ASP.NET AJAX 控件工具包 ModalPopupExtender 控件实战

两者都很好,但我想要一个更简单的,没有 JavaScript 或 iFrame 的麻烦,所以我决定使用不同的方法。

解决方案

答案是 事件冒泡

在我们的用户控件中

我们需要一个 委托,以及一个基于该委托的 事件

public delegate void DateSelectedHandler(DateTime dtDateSelected);
public event DateSelectedHandler DateSelected;

注意我们为委托指定了一个与我们要返回的值类型相同的参数(DateTime)。然后,我们创建一个与委托类型相同的事件。

现在,在 Calendar1_SelectionChanged 事件中,让我们调用我们刚刚创建的事件实例。

if (DateSelected != null)
    DateSelected(Calendar1.SelectedDate);

我们所做的是简单地将值传递给我们的自定义公共事件。现在,这个事件暴露给我们的源页面。这就是事件冒泡,事件会沿着层次结构传播(记住,冒泡排序?)。

用户控件代码隐藏

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class CalendarControl : System.Web.UI.UserControl
{
    public delegate void DateSelectedHandler(DateTime dtDateSelected);
    public event DateSelectedHandler DateSelected;

    #region Events
    protected void Calendar1_SelectionChanged(object sender, EventArgs e)
    {
        if (DateSelected != null)
            DateSelected(Calendar1.SelectedDate);
    }
    protected void Calendar1_VisibleMonthChanged(object sender, MonthChangedEventArgs e)
    {
        this.Panel1_ModalPopupExtender.Show();
    }

    protected void btnCloseMsg_Click(object sender, ImageClickEventArgs e)
    {
        Panel1_ModalPopupExtender.Hide();
    }
    #endregion

    #region Methods
    public void Show()
    {
        this.Panel1_ModalPopupExtender.Show();
    }
    #endregion
}

现在我们只需要利用我们自定义的事件。

在我们的源页面中

.aspx
<uc1:calendarcontrol ondateselected="OnDateSelected" 
         runat="server" id="ucCalendar">
</uc1:calendarcontrol>
.cs
protected void OnDateSelected(DateTime dtDateSelected)
{
    TextBox1.Text = dtDateSelected.ToShortDateString();
}

源页面代码隐藏

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class Test : System.Web.UI.Page
{
    #region Events
    protected void OnDateSelected(DateTime dtDateSelected)
    {
        TextBox1.Text = dtDateSelected.ToShortDateString();
    }
    protected void btnGetDate_Click(object sender, EventArgs e)
    {
        ucCalendar.Show();
    }
    #endregion
}

最终提示

如果你希望你的控件在回发时保持可见(例如,当用户更改月份时)

protected void Calendar1_VisibleMonthChanged(object sender, MonthChangedEventArgs e)
{
    this.Panel1_ModalPopupExtender.Show();
}

结论

所以这就是全部,构建你的用户控件,处理你的业务和验证,然后传递最终结果。借助委托和事件,我们能够为旧问题提供一个不错的解决方案。

© . All rights reserved.