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

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

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.56/5 (23投票s)

2004年12月14日

3分钟阅读

viewsIcon

340875

downloadIcon

7679

有很多关于此控件的实现,但我发现使用它们时存在一些问题,主要是 JavaScript 和 ASP.NET 的互操作性问题。此控件允许您放置一个无需回发的弹出日历,并且您可以在同一个表单中多次使用它。

Sample screenshot

引言

网络上有几种此控件的实现。 我的实现基于 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 看起来的样子

Sample screenshot

<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函数中,我做的第一件事是用当前日期初始化TextBoxText属性,只是为了不让它空白。 接下来是一个我在编写本文时学到的小技巧,当您在日历中更改月份时,它会进行回发,如果我们有多个日历,我们需要知道哪个控件真正进行了回发,这样我们就不会隐藏该特定日历; 这就是我们将访问__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属性使其不可见。 您添加的后续控件将采用连续的数字,它们的函数也是如此,允许您根据需要使用任意数量的控件。

© . All rights reserved.