#1,038 – Another Way to Prevent Certain Dates from Being Selected

You can limit the dates available for selection in a Calendar or DatePicker control in a few different ways.

If you want to prohibit some combination of dates, but have to do some calculation to figure out which dates should be prohibited, you can add a handler for the SelectedDateChanged event.

        <Label Content="Pick a day to go skydiving:"
               Margin="5"/>
        <DatePicker Margin="5,0,5,5"
                    SelectedDateChanged="DatePicker_SelectedDateChanged" />

In the handler, if the selected date is not one that you allow, you can undo the fact that it was selected.

        private void DatePicker_SelectedDateChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count > 0)
            {
                DateTime dayToDive = (DateTime)e.AddedItems[0];
                if ((dayToDive.DayOfWeek == DayOfWeek.Friday) &&
                    (dayToDive.Day == 13))
                {
                    MessageBox.Show("Dude, that's really an unlucky day to go skydiving.");
                    ((DatePicker)sender).SelectedDate = null;
                }
            }
        }

If we pick a Friday the 13th, the application warns us and then unselects the date.
1038-001

 

1038-002

#1,034 – Limiting the Range of Selectable Dates in a Calendar

The Calendar control allows selecting one or more dates.  By default, the user is allowed to select dates within the range DateTime.MinValue (1/1/0001) to DateTime.MaxValue (12/31/9999).

If you want to restrict the user to dates within a more reasonable range, you can set the DisplayDateStart and DisplayDateEnd properties.  The Calendar will then be limited to dates within that range.

        <Label Content="Pick your favorite day from the 1980s:"/>
        <Calendar DisplayDateStart="1/1/1980"
                  DisplayDateEnd="12/31/1989"/>

1034-001
1034-002

These properties also work in the DatePicker control, to limit the dates that can be selected.

 

#371 – Specifying a Default Date for a Calendar Control to Display

When you use a Calendar control, it will default to showing the current date when the application starts.

You can override the default date displayed by setting the DisplayDate property.

        <Calendar SelectionMode="SingleDate" DisplayDate="7/20/1969"/>


You can also specify a range of dates that the Calendar control is allowed to display by using the DisplayDateStart and DisplayDateEnd properties.

        <Calendar SelectionMode="SingleDate" DisplayDateStart="12/7/1941" DisplayDateEnd="8/14/1945"/>

The Calendar control will now allow selecting only dates that fall within this time period.  When you navigate to the month containing the earliest date, you’ll be unable to navigate further back in time.  Similarly, you’ll be unable to navigate to a date later than the date specified in the DisplayDateEnd property.


#368 – Specifying Blackout Dates in a Calendar Control

You can use the BlackoutDates property of a Calendar control to specify dates that a user cannot select.

The BlackoutDates property is of type CalendarBlackoutDatesCollection, which is an observable collection of CalendarDateRange objects.  You can specify a set of blackout dates for a Calendar control in XAML by defining a series of CalendarDateRange instances.

        <Calendar Name="calMuseum" SelectionMode="SingleDate">
            <Calendar.BlackoutDates>
                <CalendarDateRange Start="8/6/11" End="8/7/11"/>
                <CalendarDateRange Start="8/20/11" End="8/20/11"/>
                <CalendarDateRange Start="8/28/11" End="8/30/11"/>
            </Calendar.BlackoutDates>
        </Calendar>
        <Label Content="Choose a day to visit the museum." HorizontalContentAlignment="Center" />

The dates specified as blackout dates are not selectable by a user and will appear x‘d out on the calendar.

You can also add specific blackout dates from code-behind.

            // Blackout holidays
            calMuseum.BlackoutDates.Add(new CalendarDateRange(new DateTime(2011,1,17)));
            calMuseum.BlackoutDates.Add(new CalendarDateRange(new DateTime(2011,2,21)));
            calMuseum.BlackoutDates.Add(new CalendarDateRange(new DateTime(2011,5,30)));
            calMuseum.BlackoutDates.Add(new CalendarDateRange(new DateTime(2011,7,4)));
            calMuseum.BlackoutDates.Add(new CalendarDateRange(new DateTime(2011,9,5)));
            calMuseum.BlackoutDates.Add(new CalendarDateRange(new DateTime(2011,10,10)));
            calMuseum.BlackoutDates.Add(new CalendarDateRange(new DateTime(2011,11,11)));
            calMuseum.BlackoutDates.Add(new CalendarDateRange(new DateTime(2011,11,24)));
            calMuseum.BlackoutDates.Add(new CalendarDateRange(new DateTime(2011,12,26)));

#367 – You Can’t Bind to a Calendar Control’s SelectedDates Property

A Calendar control’s SelectedDate property (single selected date) is read/write, so you are able to use data binding to bind it to a nullable DateTime.

The SelectedDates property (collection of selected dates), on the other hand, is read-only.  This means that you can’t bind to the SelectedDates property.

If you want to store a Calendar control’s set of currently selected dates in a variable, you can handle the calendar’s SelectedDatesChanged event.

XAML fragment:

        <Calendar SelectionMode="MultipleRange" SelectedDatesChanged="Calendar_SelectedDatesChanged"/>

Code-behind, where we store selected dates in array:

        public DateTime[] MyVacation { get; set; }

        private void Calendar_SelectedDatesChanged(object sender, SelectionChangedEventArgs e)
        {
            System.Windows.Controls.Calendar cal = (System.Windows.Controls.Calendar)sender;

            MyVacation = cal.SelectedDates.ToArray();
        }

This event handler will be called whenever the user selects or unselects dates in the Calendar control.  Because we reset the MyVacation array in the handler, it will always reflect the current set of selected dates.

#366 – Binding a Calendar Control’s SelectedDate Property to a Nullable DateTime

The SelectedDate property of a Calendar control reflects the currently selected date, if the SelectionMode is SingleDate, or the first date selected if the mode is SingleRange or MultipleRange.

You can use data binding to bind the SelectedDate property to a variable of type DateTime? (nullable DateTime).

In the example below, we bind SelectedDate to the FavoriteDay property of our data context.

    <StackPanel>
        <Calendar SelectionMode="SingleDate" SelectedDate="{Binding FavoriteDay}"/>
        <Button Content="Test" Click="Button_Click" Width="80" Margin="20"/>
    </StackPanel>

In the code-behind, we define the FavoriteDay property and set the data context to the parent class that contains the property.

        public DateTime? FavoriteDay { get; set; }

        public MainWindow()
        {
            this.InitializeComponent();
            this.DataContext = this;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            string msg;

            if (FavoriteDay == null)
                msg = "I don't have a favorite day";
            else
                msg = string.Format("My favorite day is {0:D}", FavoriteDay);

            MessageBox.Show(msg);
        }

#365 – SelectedDate and SelectedDates Properties of Calendar Control

The SelectedDate property of a Calendar control is a nullable DateTime (System.DateTime?) that represents a single selected date.

The SelectedDates property is an instance of SelectedDatesCollection, which is an ObservableCollection that contains DateTime values.  It represents the set of currently selected dates.

If the SelectionMode is None, or if no date is currently selected:

  • SelectedDate is null
  • SelectedDates is an empty collection

If SelectionMode is SingleDate and a date is selected:

  • SelectedDate contains a single DateTime value
  • SelectedDates contains a single DateTime element in the collection

If SelectionMode is SingleRange or MultipleRange and at least one date is selected:

  • SelectedDate contains a single DateTime value, equivalent to the first element in the SelectedDates collection
  • SelectedDates contains a DateTime element for each date that is currently selected