[C#][Windows Formsアプリ][MonthCalendar] SelectionStart / SelectionEnd で「今日を選択」する

スポンサーリンク

はじめに

本記事では、Windows Forms の MonthCalendar コントロールで、SelectionStart / SelectionEnd を使って「今日(本日の日付)を選択」する方法を、初心者にもわかりやすく解説します。実運用でありがちな「フォーム起動時に今日を選びたい」「ボタンでいつでも今日に戻したい」というニーズに対し、最小コードと実践テクニック(つまづき対策)をまとめました。

説明

MonthCalendar は単一日だけでなく範囲選択もできます。
「今日だけを選択」したい場合は、SelectionStartSelectionEnd に同じ日付(DateTime.Today)を代入します。これで選択範囲の開始と終了が同じ日=単一日の選択になります。

ポイント:

DateTime.Today は現在日時の 時刻を 00:00:00 に切り捨てた日付を返します。
SelectionStartSelectionEnd順序を気にせず同じ日付を入れれば 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() で「今日」を算出し、SelectionStartSelectionEnd に同じ日付をセット=単一日選択。
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.TodaySelectionEnd = DateTime.Today の 2 行で完了します。
必要に応じて MaxSelectionCount = 1MinDate/MaxDate の丸め、日付変更の再設定(Timer)を組み合わせると、実用度がさらに高まります。まずは最小サンプルをそのままコピペして、挙動を確認してみてください。

Please follow and like us:

コメント

タイトルとURLをコピーしました