一个 ASP.NET 弹出日历的实现






3.56/5 (23投票s)
2004年12月14日
3分钟阅读

340875

7679
有很多关于此控件的实现,但我发现使用它们时存在一些问题,主要是 JavaScript 和 ASP.NET 的互操作性问题。此控件允许您放置一个无需回发的弹出日历,并且您可以在同一个表单中多次使用它。
引言
网络上有几种此控件的实现。 我的实现基于 Paul Kilmer 的实现,但在我无法使其工作后进行了许多更改; 许多更改是将 HTML 控件更改为实际的 ASP.NET 控件,因为这会在控件的后台代码中给我更好的控制,您将在代码中看到这一点。
创建控件
首先,您需要创建一个新控件,在本例中,我将其命名为ctlCalendar
。 在此控件中,您需要从 Web Forms 工具箱添加一个TextBox
(TextBox1
),从 HTML 工具栏添加一个Button
(Button1
),从 Web Forms 工具箱添加一个Panel
(Panel1
),最后在此Panel
内部,从 Web Forms 工具箱添加一个Calendar
控件 (Calendar1
)。 请注意,我使用了 HTML 工具栏中的Button1
,因为我需要它在用户单击时不回发。
这就是你的控件的 HTML 看起来的样子
<asp:textbox id="TextBox1" runat="server"></asp:textbox>
<input type="button" id="Button1" runat="server" value="..."><br>
<asp:Panel id="pnlCalendar" runat="server"
style="POSITION: absolute">
<asp:calendar id="Calendar1" runat="server" CellPadding="4"
BorderColor="#999999" Font-Names="Verdana" Font-Size="8pt"
Height="180px" ForeColor="Black" DayNameFormat="FirstLetter"
Width="200px" BackColor="White">
<TodayDayStyle ForeColor="Black" BackColor="#CCCCCC"></TodayDayStyle>
<SelectorStyle BackColor="#CCCCCC"></SelectorStyle>
<NextPrevStyle VerticalAlign="Bottom"></NextPrevStyle>
<DayHeaderStyle Font-Size="7pt" Font-Bold="True" BackColor="#CCCCCC">
</DayHeaderStyle>
<SelectedDayStyle Font-Bold="True" ForeColor="White" BackColor="#666666">
</SelectedDayStyle>
<TitleStyle Font-Bold="True" BorderColor="Black" BackColor="#999999">
</TitleStyle>
<WeekendDayStyle BackColor="LightSteelBlue"></WeekendDayStyle>
<OtherMonthDayStyle ForeColor="#808080"></OtherMonthDayStyle>
</asp:calendar>
</asp:Panel>
创建功能
现在,我们将使用两个函数来创建功能;第一个是Page_Load
,我们在其中初始化我们的控件,以及Calendar1_SelectionChanged
。
private void Page_Load(object sender, System.EventArgs e)
{
if (!Page.IsPostBack)
{
this.TextBox1.Text = System.DateTime.Now.ToShortDateString();
this.pnlCalendar.Attributes.Add("style",
"DISPLAY: none; POSITION: absolute");
}
else
{
string id = Page.Request.Form["__EVENTTARGET"].Substring(0,
Page.Request.Form["__EVENTTARGET"].IndexOf(":"));
if (id != this.ID)
{
this.pnlCalendar.Attributes.Add("style",
"DISPLAY: none; POSITION: absolute");
}
else
{
this.pnlCalendar.Attributes.Add("style","POSITION: absolute");
}
}
Page.RegisterClientScriptBlock("Script_Panel" + this.ID,
"<script> function On"+this.ID+"Click() { if(" +
this.ID + "_pnlCalendar.style.display == \"none\") "
+ this.ID + "_pnlCalendar.style.display = \"\"; else "
+ this.ID+"_pnlCalendar.style.display = \"none\"; } </script>");
this.Button1.Attributes.Add("OnClick","On"+this.ID+"Click()");}
在Page_Load
函数中,我做的第一件事是用当前日期初始化TextBox
的Text
属性,只是为了不让它空白。 接下来是一个我在编写本文时学到的小技巧,当您在日历中更改月份时,它会进行回发,如果我们有多个日历,我们需要知道哪个控件真正进行了回发,这样我们就不会隐藏该特定日历; 这就是我们将访问__EVENTTARGET
隐藏字段的地方,它会告诉我们哪个日历正在活动。
string id = Page.Request.Form["__EVENTTARGET"].Substring(0,
Page.Request.Form["__EVENTTARGET"].IndexOf(":"));
然后我只是比较一下它是否不是我正在使用的日历,我会隐藏它,否则就让它保持绝对位置。
if (id != this.ID)
{
this.TextBox1.Text = System.DateTime.Now.ToShortDateString();
this.pnlCalendar.Attributes.Add("style",
"DISPLAY: none; POSITION: absolute");
}
else
{
this.pnlCalendar.Attributes.Add("style","POSITION: absolute");
}
在接下来的几行中,我注册一个客户端脚本,这是实际的 JavaScript,它将在单击按钮时显示日历,它看起来有点复杂,因此我将深入解释它。
当您将多个控件添加到同一个表单时,每个控件都有自己的名称(在本例中为ctlCalendar
),后跟一个数字(对于第一个控件,它将是CtlCalendar1
)。 知道了这一点,我编写了一行代码,它将为每个创建的控件创建一个 JavaScript 函数,使用this.ID
属性
Page.RegisterClientScriptBlock("Script_" + this.ID,
"<script> function On"+this.ID+"Click() { if("+this.ID+
"_pnlCalendar.style.display == \"none\") "+this.ID+
"_pnlCalendar.style.display = \"\"; else "+this.ID+
"_pnlCalendar.style.display = \"none\"; } </script>");
然后将该函数添加到Button
本身。
this.Button1.Attributes.Add("OnClick","On"+this.ID+"Click()");
此外,为了访问Panel
的实际属性,您需要知道您的Panel
的名称。 当控件生成时,此名称由控件的名称 (ctlCalendar1
) 组成,然后是Panel
的名称 (Panel1
),并用下划线分隔 (ctlCalendar1_Panel1
用于添加到页面的第一个ctlCalendar
)。
让我们看看为页面中的第一个日历生成的 JavaScript 代码
<Script>
function OnCtlCalendar1Click()
{
if(CtlCalendar1_pnlCalendar.style.display == "none")
CtlCalendar1_pnlCalendar.style.display = "";
else
CtlCalendar1_pnlCalendar.style.display = "none";
}
</script>
在这里,我们看到该函数如何拥有自己的名称 (OnCtlCalendar1Click()
),并且我们还生成了Panel
的最终名称 (CtlCalendar1_pnlCalendar
),以便使用display
属性使其不可见。 您添加的后续控件将采用连续的数字,它们的函数也是如此,允许您根据需要使用任意数量的控件。