I came across this cool little article on creating a dropdown calendar control recently. It basically uses dhtml to popup an asp.net calendar control when you need it, rather than opening up a new window. While it's useful, it's dhtml is IE specific, so I made a few quick changes and came up with:
CalendarControl.ascx:
<%@ Control Language="c#" AutoEventWireup="false" Codebehind="CalendarControl.ascx.cs"
Inherits="CalendarControl.CalendarControl" %>
<asp:textbox runat="server" id="calendarDateBox" />
<input type="button" value="..." onclick="<%=calendarDiv.ClientID%>_ToggleCalendar()">
<div runat="server" id="calendarDiv" style="display:none;position:absolute;">
<asp:Calendar backcolor="#ffffff" id="calendar" runat="server"></asp:Calendar>
</div>
<script language="javascript">
function <%=calendarDiv.ClientID%>_ToggleCalendar()
{
var cal = document.getElementById('<%=calendarDiv.ClientID%>');
if ( cal.style.display == "none")
{
cal.style.display = "";
}
else
{
cal.style.display = "none";
}
}
</script>
CalendarPopup.ascx.cs
using System;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
namespace CalendarControl
{
public class CalendarControl : System.Web.UI.UserControl, INamingContainer
{
protected System.Web.UI.WebControls.Calendar calendar;
protected System.Web.UI.HtmlControls.HtmlGenericControl calendarDiv;
protected System.Web.UI.WebControls.TextBox calendarDateBox;
private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here
}
#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///
private void InitializeComponent()
{
this.calendar.SelectionChanged += new System.EventHandler(this.calendar_SelectionChanged);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
private void calendar_SelectionChanged(object sender, System.EventArgs e)
{
calendarDateBox.Text = calendar.SelectedDate.ToShortDateString();
Control div = Page.FindControl( "calendarDiv" );
calendarDiv.Style.Add("display", "none");
}
}
}
Also, I added in the ability to have multiple calendar controls on the page at once. The main trick was to have the control inherit from the INamingContainer interface, which automattically give any server controls unique names. To get the client side functions to sink up I used the div's (now a server control) ClientId via <%=calendarDiv.ClientID%>, although there is probably a better way to do this. This allowed each control to have it's own client side function which calls the specific div. With some work it's probably possible to eliminate the postback for the date selection, but the control as should work fine for most situations as is.