はじめに
本記事では、Windows Forms の MonthCalendar コントロールで、SelectionStart / SelectionEnd を使って「今日(本日の日付)を選択」する方法を、初心者にもわかりやすく解説します。実運用でありがちな「フォーム起動時に今日を選びたい」「ボタンでいつでも今日に戻したい」というニーズに対し、最小コードと実践テクニック(つまづき対策)をまとめました。
説明
MonthCalendar は単一日だけでなく範囲選択もできます。
「今日だけを選択」したい場合は、SelectionStart と SelectionEnd に同じ日付(DateTime.Today)を代入します。これで選択範囲の開始と終了が同じ日=単一日の選択になります。
ポイント:
・DateTime.Today は現在日時の 時刻を 00:00:00 に切り捨てた日付を返します。
・SelectionStart と SelectionEnd は 順序を気にせず同じ日付を入れれば OK です(範囲が 1 日になります)。
・MaxSelectionCount の既定値は 7 ですが、単一日選択には影響ありません(1 日 ≤ 7 日)。
サンプルコード
フォーム起動時に「今日を選択」し、ボタンでもいつでも今日に戻せる最小サンプルです。
さらに、ログで実際の選択日を確認でき、DateChanged が発火することも分かります。
using System;
using System.Drawing;
using System.Windows.Forms;
namespace MonthCalendarSelectToday
{
public class MainForm : Form
{
private MonthCalendar monthCalendar;
private Button btnSelectToday;
private ListBox listBoxLog;
public MainForm()
{
Text = "MonthCalendar - 今日を選択 (SelectionStart/End)";
Width = 640;
Height = 420;
monthCalendar = new MonthCalendar
{
Location = new Point(20, 20),
MaxSelectionCount = 31 // 範囲選択を許す場合の上限(単一日は問題なし)
};
btnSelectToday = new Button
{
Text = "今日を選択",
Location = new Point(20, 200),
Width = 200
};
listBoxLog = new ListBox
{
Location = new Point(300, 20),
Width = 300,
Height = 300
};
// イベント: 選択が変わるたびにログ
monthCalendar.DateChanged += (s, e) =>
{
Log($"DateChanged Start={e.Start:yyyy-MM-dd}, End={e.End:yyyy-MM-dd}");
};
// ボタン: いつでも「今日」に戻す
btnSelectToday.Click += (s, e) => SelectToday();
Controls.Add(monthCalendar);
Controls.Add(btnSelectToday);
Controls.Add(listBoxLog);
// 起動時に今日を選択
Load += (s, e) => SelectToday();
}
/// <summary>
/// SelectionStart / SelectionEnd を同日に設定して「今日だけを選択」する
/// </summary>
private void SelectToday()
{
var today = DateTime.Today;
// MinDate / MaxDate を考慮(念のため範囲内に収める)
if (today < monthCalendar.MinDate) today = monthCalendar.MinDate; if (today > monthCalendar.MaxDate) today = monthCalendar.MaxDate;
// 単一日選択:開始と終了に同じ日付を設定
monthCalendar.SelectionStart = today;
monthCalendar.SelectionEnd = today;
Log($"[Set] Today = {today:yyyy-MM-dd}");
}
private void Log(string message)
{
listBoxLog.Items.Insert(0, $"{DateTime.Now:HH:mm:ss.fff} {message}");
}
[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.Run(new MainForm());
}
}
}
コード解説(ポイントだけ最短理解)
・SelectToday() で「今日」を算出し、SelectionStart と SelectionEnd に同じ日付をセット=単一日選択。
・MinDate/MaxDate を越える可能性があるアプリでは、範囲内に丸めておくと安全。
・起動時(Load)とボタン押下で共通メソッドを呼ぶだけのシンプル設計。
つまづきポイント
1) 「1 日だけ選ばせたいのにドラッグで範囲になってしまう」
単一日固定にしたい場合は、MaxSelectionCount = 1 を明示するとユーザー操作でも 1 日以上は選べません。
2) 「今日にセットしたのにイベントが動かない?」
SelectionStart/End をコードで変更すると DateChanged は発火しますが、DateSelected は発火しません(ユーザー確定操作のみ)。必要なイベントを正しく使い分けましょう。
3) 「アプリを開いたまま日付が変わったら?」
「常にカレンダーは今日を指してほしい」要件なら、日付変更(深夜 0 時)を検知して SelectToday() を再実行する仕組み(Timer で 1 分おきに監視など)を足すと実務で安定します。
4) 「MinDate/MaxDate を設定したらエラー」
DateTime.Today が範囲外だと例外は出ませんが、意図しない日付になることがあります。上のサンプルのように範囲内へ丸めると安全です。
まとめ
「今日だけを選択」は、SelectionStart = DateTime.Today と SelectionEnd = DateTime.Today の 2 行で完了します。
必要に応じて MaxSelectionCount = 1 や MinDate/MaxDate の丸め、日付変更の再設定(Timer)を組み合わせると、実用度がさらに高まります。まずは最小サンプルをそのままコピペして、挙動を確認してみてください。

コメント