WPF 標準コントロールデモアプリ › DatePicker

DatePicker Inputs

DatePicker は、日付を入力するテキスト欄と、カレンダーのポップアップを開くボタンを組み合わせたコントロールです。選んだ日付は null 許容の DateTime です。

値は null 許容の日付:DateTime? にバインドする

DatePicker の値は SelectedDate で、型は DateTime? です。日付を選んでいないときは null になり、既定で TwoWay にバインドされます。テキスト欄はこの値を文字列で表示し、日付を入力して Enter キーを押すと値が設定されます。テキスト欄を空にして Enter キーを押すと null になりました。ユーザーが選ぶまで空にしておく期日などは、DateTime? のプロパティにバインドします。DateTime のプロパティにバインドした状態で null にすると、バインドエラーになりました。ソースは元の日付のままで、DatePicker の Validation.HasError が True になりました。

DisplayDate はカレンダーに表示する月です。新しく作った DatePicker では今日の日付でした。SelectedDate を 2026-04-15 にすると、DisplayDate も同じ日に移りました。その後で DisplayDate を変えても SelectedDate は変わりませんでした。

カレンダーのポップアップは Calendar コントロールです。IsDropDownOpen はポップアップが開いているかどうかを表し、既定で TwoWay にバインドされます。ウィンドウを表示する前に True にしても例外は出ず、ウィンドウが表示された時点でポップアップは開いていました。

範囲が制限するのはカレンダーだけ

DisplayDateStart と DisplayDateEnd は、カレンダーで選べる最初と最後の日付です。2026-04-10〜2026-04-20 の範囲では、ポップアップの 04-05 の日付ボタンは無効になりました。範囲が効くのはここだけです。コードから SelectedDate を 04-05 にしても、Text に “4/5/2026” を設定しても、テキスト欄に “4/5/2026” と入力して Enter キーを押しても、日付は 04-05 になりました。例外も DateValidationError も発生しませんでした。範囲の検証は ViewModel で行います。

選択中の日付より後の DisplayDateStart も効きません。04-10 を選んだ状態で DisplayDateStart = 04-15 とすると、04-10 に引き戻されました。そのため、開始日と終了日の 2 つの DatePicker で、終了日側の DisplayDateStart を開始日にバインドしても、終了日側にすでにそれより前の日付が入っていると効きません。2 つの日付の前後は ViewModel で確かめます。

選ばせたくない日は BlackoutDates に入れます。範囲と違い、BlackoutDates は守られます。コードから該当日を SelectedDate に設定すると ArgumentOutOfRangeException が発生して元の日付のままになり、ポップアップではその日が選択不可(IsBlackedOut)として示されました。

条件 結果
SelectedDate = 04-15: DisplayDate / 続けて DisplayDate = 07-01: SelectedDate 2026-04-15 / 2026-04-15
範囲外をコードから: SelectedDate = 04-05 例外なし; SelectedDate 2026-04-05
範囲外を Text から: Text = "4/5/2026" 例外なし; SelectedDate 2026-04-05, Text "4/5/2026"
範囲外を入力: "4/5/2026" + Enter SelectedDate 2026-04-05, Text "4/5/2026", DateValidationError 0
範囲内を入力: "4/18/2026" + Enter SelectedDate 2026-04-18, Text "4/18/2026", DateValidationError 0
解析できない文字列を入力: "abc" + Enter SelectedDate 2026-04-15, Text "4/15/2026", DateValidationError 1 ("abc")
文字列を消して Enter SelectedDate null, Text "", DateValidationError 0
カレンダーのポップアップ、日付ボタン 2026-04-05 IsEnabled False, IsBlackedOut False, IsInactive False
カレンダーのポップアップ、日付ボタン 2026-04-12 IsEnabled True, IsBlackedOut False, IsInactive False
BlackoutDates 04-12..04-13、コードから SelectedDate = 04-12 ArgumentOutOfRangeException; SelectedDate 2026-04-15
カレンダーのポップアップ、日付ボタン 2026-04-12 IsEnabled True, IsBlackedOut True
SelectedDate 04-10、続けて DisplayDateStart = 04-15 例外なし; DisplayDateStart 2026-04-10, SelectedDate 2026-04-10
Text = "4/15/2026" 例外なし; SelectedDate 2026-04-15, Text "4/15/2026"
Text = "2026-04-15" 例外なし; SelectedDate 2026-04-15, Text "4/15/2026"
Text = "April 15, 2026" 例外なし; SelectedDate 2026-04-15, Text "4/15/2026"
Text = "15/4/2026" 例外なし; SelectedDate null, Text ""

xml:lang="en-US" での範囲、BlackoutDates、入力の結果。.NET 10 / Windows 11 で計測。

Text の設定と、テキスト欄への入力の違い

ここでの日付の解析と表示には xml:lang="en-US" を指定しました。Text は日付の文字列です。SelectedDate と違い、既定では TwoWay にバインドされません。設定するとすぐに DatePicker のカルチャで解析され、”4/15/2026”・”2026-04-15”・”April 15, 2026” はいずれも 2026-04-15 になり、Text は “4/15/2026” に変わりました。解析できない文字列(en-US での “15/4/2026”)を設定すると、SelectedDate は null になりました。

テキスト欄に入力した場合は動きが異なり、”abc” と入力して Enter キーを押すと DateValidationError が発生し、日付も文字列も元のまま戻りました。入力が受け付けられなかったことを伝えるには、DateValidationError を処理します。処理しないと、テキスト欄は何も知らせずに元の日付へ戻ります。

スタイルとカルチャで決まる既定値

既定値のうち 2 つは既定のスタイルから与えられ、プロパティのメタデータと食い違います。IsTodayHighlighted はメタデータでは False ですが、既定のスタイルが True を設定するため、無効にしない限り今日には印が付きます。False にすると、日付ボタンの表示状態が Today から RegularDay に変わり、今日の印が透明になりました。ボタンは有効なままで、今日の日付は選べます。

SelectedDateFormat の値は Short と Long の 2 つだけです。メタデータでは Long で、実際の既定値は既定のスタイルが設定する Short です。カルチャごとの表示と、これ以外の形式で表示する方法は、DatePicker の表示形式をカスタマイズする方法で実測しています。SelectedDate が保持するのは文字列ではなく DateTime なので、記事では DatePicker のテキスト部分の側で形式を変えています。

カレンダーの左端の列の曜日である FirstDayOfWeek は、ポップアップの Calendar にも同じ値が渡りました。新しく作った DatePicker は、スレッドの現在のカルチャから値を取ります。en-US と ja-JP では Sunday、de-DE と fr-FR では Monday でした。ユーザーのカルチャと違う曜日から始めたいときだけ、明示的に設定します。

デモアプリで試す

デモアプリの DatePicker のページ。左にコントロールの一覧、右に最初の節の DisplayDate

デモアプリの DatePicker のページには、SelectedDate、DisplayDate、DisplayDateStart と DisplayDateEnd、FirstDayOfWeek、IsDropDownOpen、IsTodayHighlighted、SelectedDateFormat、Text の欄があります。DisplayDate の欄では、別の DatePicker で選んだ日付(今日の 1 か月後)を DisplayDate にバインドしています。範囲の欄は直前の月曜日から次の金曜日までで、IsDropDownOpen の欄のチェックボックスはポップアップを開閉するだけでなく、ポップアップの状態にも追従します。Text の欄では、テキストボックスから OneWay でバインドしています。各欄の下の「Show Code」リンクで、その欄の XAML を表示できます。次の XAML は、DisplayDate Range (Start/End) の欄(DatePickerUsageControl.xaml)から、スタイルと周囲の GroupBox を省き、名前空間の宣言を加えたものです。DateTimeAdvancedConverter はデモアプリのコンバーターで、今日から直前の月曜日と次の金曜日を求めます。converters はデモアプリ独自のコンバーターの接頭辞です。

<StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:sys="clr-namespace:System;assembly=mscorlib"
            xmlns:converters="clr-namespace:WPFStandardControlDemoApp.Common.Converters">
  <DatePicker x:Name="DisplayDateStartSourceDatePicker"
              SelectedDate="{Binding Source={x:Static sys:DateTime.Now},
                                     Converter={converters:DateTimeAdvancedConverter Operation=Previous, TargetDay=Monday},
                                     Mode=OneTime}" />
  <DatePicker x:Name="DisplayDateEndSourceDatePicker"
              SelectedDate="{Binding Source={x:Static sys:DateTime.Now},
                                     Converter={converters:DateTimeAdvancedConverter Operation=Next, TargetDay=Friday},
                                     Mode=OneTime}" />

  <DatePicker x:Name="DisplayDateRangeDatePicker"
              DisplayDateEnd="{Binding SelectedDate, ElementName=DisplayDateEndSourceDatePicker}"
              DisplayDateStart="{Binding SelectedDate, ElementName=DisplayDateStartSourceDatePicker}"
              SelectedDate="{x:Static sys:DateTime.Now}" />
</StackPanel>

3 つ目の DatePicker には最初から今日が選ばれています。そのため、1 つ目の DatePicker で開始日を今日より後にしても、DisplayDateStart の説明のとおり、範囲は今日より後には狭まりません。

関連するコントロールと記事

ソースコードと計測の方法

このページの挙動の記述は、すべて .NET 10 / Windows 11 で実際に動かして確かめたものです。計測には、このサイトのスクリーンショット生成ツールの DatePickerDemoScene を使いました。入力は、DatePicker のテキスト部分に文字列を設定して Enter キーのイベントを送って再現し、カレンダーはポップアップを開いて日付ボタンの状態を読みました。

GitHub で DatePicker のソースコードを見る →