一个 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属性使其不可见。 您添加的后续控件将采用连续的数字,它们的函数也是如此,允许您根据需要使用任意数量的控件。
