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






4.81/5 (11投票s)
如何从模态弹出窗口返回值。
引言
你可能在 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>
源页面
只需要一个文本框,用于接收结果,和一个按钮来显示弹出窗口。
<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
中。
问题
主要问题是:如何让调用页面**感知**你的自定义控件? 也就是说,我们的控件是一个日历,我们希望源页面中的文本框**看到**我们刚刚选择的日期。
我发现了以下解决方案
两者都很好,但我想要一个更简单的,没有 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();
}
结论
所以这就是全部,构建你的用户控件,处理你的业务和验证,然后传递最终结果。借助委托和事件,我们能够为旧问题提供一个不错的解决方案。