Ajax Control Toolkit の CalendarExtender を、下の画像のようにテキストボックスなし(実際は非表示)で、img 要素(普通のボタンでも可)をクリックして表示し、ユーザーがカレンダー上で選択した日付をサーバー側に送信する方法を書きます。
今時 CalendarExtender を使うことはあまりなさそうで、しかもこの記事に書いてあるような特殊な使い方をすることはまずなさそうですが、せっかく考えたので備忘録として書いておくことにしました。
CalendarExtender の基本的な使い方については、DevExpress のデモページ「Calendar Demonstration」と、@IT の記事「Calendarコントロールで日付入力ボックスを定義するには?」が参考になると思いますので一読されることをお勧めします。
カレンダーを img 要素(または普通のボタン)をクリックして表示する方法ですが、DevExpress のデモページの「Calendar with an associated button」と @IT の記事の「補助カレンダーを任意のボタンから起動する」を見てください。
この記事では、DevExpress のデモページと同じ画像を img 要素を使って表示し、CalendarExtender の PopupButtonID プロパティに img 要素の id を設定して、その img 要素をクリックしてカレンダーを表示します。img 要素に代えて <button type="button"> も使えます。ただし、クリックするとポストバックが起こる Button コントロールなどを使う場合は、ポストバックが起こらないように処置する必要があるので注意してください。
CalendarExtender の対象となるテキストボックスを指定する TargetControlID の設定は必須です。なので必ずテキストボックスをページに配置する必要があります。非表示にしたい場合は CSS で display: none; を設定してください。TextBox.Visible プロパティを false に設定するのはダメです。
カレンダーの表示位置はデフォルトでは自動的にテキストボックス直下になります。テキストボックスを非表示にする場合は自力で JavaScript を書いてカレンダーの表示位置を設定する必要があります。
その方法は Code Project の記事 Ajax CalendarExtender pop up position の Solution 1 を参考にさせてもらいました。
最後に、ユーザーが選択した日付をサーバーに送信する方法ですが、選択した時点で日付はテキストボックスに自動的に入力されますので、何らかの手段でポストバックをかければサーバー側で Text プロパティから取得できます。
CalendarExtender の OnClientDateSelectionChanged プロパティに JavaScript のリスナを設定してそこで取得し、Ajax を使ってサーバーに送信することもできます。
以上を実装したサンプルコードを下に載せておきます。この記事の上の画像を表示したものです。
CalendarExtender.aspx.cs
using System.Web.UI;
namespace WebForms1
{
public partial class CalendarExtender : System.Web.UI.Page
{
protected void Page_Init(object sender, EventArgs e)
{
// マスターページに配置した ScriptManager のプロパティ
// EnableScriptGlobalization を true に設定する
ScriptManager sm = ScriptManager.GetCurrent(this.Page);
sm.EnableScriptGlobalization = true;
}
protected void Page_Load(object sender, EventArgs e)
{
// ユーザーが選択した日付を取得・表示
Label1.Text = TextBox1.Text;
}
}
}
CalendarExtender.aspx.cs
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master"
AutoEventWireup="true" CodeBehind="CalendarExtender.aspx.cs"
Inherits="WebForms1.CalendarExtender" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeaderContent" runat="server">
<script type="text/javascript">
// Calendar の表示位置を img 要素直下に調整する
function onCalendarShown(sender, args) {
var img = $get('image1');
sender._popupDiv.parentElement.style.top =
img.offsetTop + img.height + 'px';
sender._popupDiv.parentElement.style.left =
img.offsetLeft + 'px';
}
// ユーザーが日付を選択すると発生するイベントのリスナ
function sendResult(sender) {
// 選択した日付は以下のようにして取得できる
var selectedDate = sender.get_selectedDate();
// ポストバックすればサーバー側では TextBox1.Text
// プロパティから選択した日付を取得できる
var btn = $get('<%=Button1.ClientID %>');
btn.click();
}
</script>
<style type="text/css">
/* TextBox1 を非表示にする */
.style1 {
display: none;
}
</style>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h3>Ajax Control Toolkit CalendarExtender</h3>
<asp:TextBox ID="TextBox1" runat="server" CssClass="style1">
</asp:TextBox>
<%--PopupButtonID に設定するのはサーバーコントロールでなくても可--%>
<img src="images/Calendar_scheduleHS.png" id="image1" alt="" />
<ajaxToolkit:CalendarExtender ID="CalendarExtender1"
runat="server"
PopupButtonID="image1"
TargetControlID="TextBox1"
DaysModeTitleFormat="yyyy年M月"
TodaysDateFormat="yyyy年M月d日"
Format="yyyy/MM/dd"
OnClientDateSelectionChanged="sendResult"
OnClientShown="onCalendarShown" />
<br />
<%--ポストバックするための Button コントロール--%>
<asp:Button ID="Button1" runat="server" Text="PostBack" />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</asp:Content>
なお、本題とは関係ないことですが、カレンダー上の日付の表示はデフォルトではなく、先の記事「CalendarExtender の日付の表示」に書いたように日本語形式にしています。