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 のページには、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 の説明のとおり、範囲は今日より後には狭まりません。
関連するコントロールと記事
- DatePicker の表示形式をカスタマイズする方法 — カルチャごとの
SelectedDateFormatの表示の実測と、独自の形式で表示する方法を扱います。 - TextBox — DatePicker のテキスト部分は TextBox の派生の
DatePickerTextBoxです。
ソースコードと計測の方法
このページの挙動の記述は、すべて .NET 10 / Windows 11 で実際に動かして確かめたものです。計測には、このサイトのスクリーンショット生成ツールの DatePickerDemoScene を使いました。入力は、DatePicker のテキスト部分に文字列を設定して Enter キーのイベントを送って再現し、カレンダーはポップアップを開いて日付ボタンの状態を読みました。