かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

WPF4.5入門 その28 「Calendarコントロール」

Calendarコントロールは、名前の通りカレンダーを画面に表示してユーザーに日付を選択してもらうためのコントロールです。Calendarコントロールの代表的な機能を以下に示します。

  1. 表示内容を1か月、1年、10年に設定できます。
  2. 複数の日付(単一選択と複数選択の組み合わせ)の選択ができます。
  3. 選択不可の日付を設定できます。
  4. Calendarコントロールに表示される日付の範囲を設定します。
  5. 今日の日付を強調表示できます

基本的な使い方

Calendarコントロールの基本的な使い方を示します。WindowにCalendarコントロールを置くと以下のような表示になります。このように1月ぶんの日付が表示されます。
f:id:okazuki:20130708232055p:plain
ここにボタンを置いて、選択日をメッセージボックスで表示してみます。コードは以下のようになります。

<Window x:Class="CalendarSample01.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Calendar x:Name="calendar" />
        <Button Content="Show SelectedDate" Grid.Row="1" Click="Button_Click"/>
    </Grid>
</Window>

ボタンのクリックイベントハンドラのコードを以下に示します。

private void Button_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show(this.calendar.SelectedDate.ToString());
}

プログラムを実行して、日付を選択せずにボタンを押すと以下のように空のメッセージボックスが表示されます。SelectedDateプロパティは、DateTime?型のため、未選択時はデータを持ちません。カレンダー内の日付を選択して、ボタンを押すと以下のように選択された日が表示されます。
f:id:okazuki:20130708232200p:plain

選択方法のカスタマイズ

Calendarコントロールは、以下のプロパティを設定することで、日付の選択を制御することができます。

プロパティ 説明
CalendarSelectionMode SelectionMode { get; set; } 日付の選択方法を設定します。以下の値から設定できます。MultipleRange:複数の範囲選択ができます,None:何も選択できません。,SingleDate:単一の日付を選択できます。, SingleRange:単一の日付の範囲を選択できます。
SelectedDatesCollection SelectedDates { get; } 選択された日付のコレクションです。AddRangeメソッドを使って指定した日付の範囲を追加することができます。SelectionModeプロパティにMultipleRangeかSingleRangeが設定されているときのみ、AddRangeメソッドが動きます。
DateTime? SelectedDate { get; set; } 単一の選択された日付を取得または設定します。

このほかに、BlackoutDatesプロパティを使うことで選択できない日付をカレンダーに設定できます。

プロパティ 説明
CalendarBlackoutDatesCollection BlackoutDates { get; } 選択できない日付のコレクションを返します。AddメソッドでCalendarDateRangeを追加することで、選択できない日付の範囲指定を行います。また、AddDatesInPastメソッドを呼ぶことで過去の日付を選択できないようにします。

これらのプロパティを組み合わせることで、柔軟な日付選択の手段をユーザーに提供できます。以下に、今日より前の日付と、翌日から4日間は選択できないようにして、それ以外の日付を複数選択可能にする場合のコード例を示します。
まず、ページのXAMLです。XAMLでは、複数選択が可能なことをSelectionModeプロパティで指定しています。

<Window x:Class="CalendarSample02.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Calendar x:Name="calendar" 
                  SelectionMode="MultipleRange" />
        <Button Content="Show SelectedDate" Grid.Row="1" Click="Button_Click"/>
    </Grid>
</Window>

コードビハインドでは、今日より前の日付の無効化と翌日から4日間を無効化しています。ボタンのクリックイベントではSelectionDatesプロパティから選択された日付を改行区切りの文字列にして表示しています。

using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace CalendarSample02
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            // 今日より前は、選択不可能にする。
            this.calendar.BlackoutDates.AddDatesInPast();
            // 翌日から4日間も選択不可能にする
            this.calendar.BlackoutDates.Add(
                new CalendarDateRange(
                    DateTime.Today.AddDays(1),
                    DateTime.Today.AddDays(4)));
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // 選択された日付を連結して表示
            var selected = string.Join(Environment.NewLine, 
                this.calendar.SelectedDates.Select(d => d.ToString()));
            MessageBox.Show(selected);
        }
    }
}

実行して、何日か日付を選択してボタンをクリックした結果を以下に示します。日付を複数選択できていることと、指定した範囲の日付が選択できないように×印がついています。

f:id:okazuki:20130708233709p:plain

表示範囲のカスタマイズ

CalendarコントロールのDisplayDateStartプロパティとDisplayDateEndプロパティを使うことで、カレンダーで選択可能な日付の範囲を指定できます。

プロパティ 説明
DateTime? DisplayDateStart { get; set; } カレンダーの日付の範囲の最初の日付を取得または設定します。
DateTime? DisplayDateEnd { get; se;t } カレンダーの日付の範囲の最後の日付を取得または設定します。

以下にXAMLでDisplayDateStartプロパティとDisplayDateEndプロパティで2013/07/01から2013/07/15までの範囲を設定した場合の例を示します。

<Window x:Class="CalendarSample03.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Calendar x:Name="calendar" 
                  DisplayDateStart="2013/07/01"
                  DisplayDateEnd="2013/07/15"/>
        <Button Content="Show SelectedDate" Grid.Row="1" Click="Button_Click"/>
    </Grid>
</Window>

実行すると以下のような結果になります。表示されている日付が指定した範囲に制限されていることが確認できます。
f:id:okazuki:20130708233912p:plain

過去記事