Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / Calendar.cs / 1305600 / Calendar.cs
//----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
namespace System.Windows.Controls
{
///
/// Represents a control that enables a user to select a date by using a visual calendar display.
///
[TemplatePart(Name = Calendar.ElementRoot, Type = typeof(Panel))]
[TemplatePart(Name = Calendar.ElementMonth, Type = typeof(CalendarItem))]
public class Calendar : Control
{
#region Constants
private const string ElementRoot = "PART_Root";
private const string ElementMonth = "PART_CalendarItem";
private const int COLS = 7;
private const int ROWS = 7;
private const int YEAR_ROWS = 3;
private const int YEAR_COLS = 4;
private const int YEARS_PER_DECADE = 10;
#endregion Constants
#region Data
private DateTime? _hoverStart;
private DateTime? _hoverEnd;
private bool _isShiftPressed;
private DateTime? _currentDate;
private CalendarItem _monthControl;
private CalendarBlackoutDatesCollection _blackoutDates;
private SelectedDatesCollection _selectedDates;
#endregion Data
#region Public Events
public static readonly RoutedEvent SelectedDatesChangedEvent = EventManager.RegisterRoutedEvent("SelectedDatesChanged", RoutingStrategy.Direct, typeof(EventHandler), typeof(Calendar));
///
/// Occurs when a date is selected.
///
public event EventHandler SelectedDatesChanged
{
add { AddHandler(SelectedDatesChangedEvent, value); }
remove { RemoveHandler(SelectedDatesChangedEvent, value); }
}
///
/// Occurs when the DisplayDate property is changed.
///
public event EventHandler DisplayDateChanged;
///
/// Occurs when the DisplayMode property is changed.
///
public event EventHandler DisplayModeChanged;
///
/// Occurs when the SelectionMode property is changed.
///
public event EventHandler SelectionModeChanged;
#endregion Public Events
///
/// Static constructor
///
static Calendar()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Calendar), new FrameworkPropertyMetadata(typeof(Calendar)));
KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(Calendar), new FrameworkPropertyMetadata(KeyboardNavigationMode.Once));
KeyboardNavigation.DirectionalNavigationProperty.OverrideMetadata(typeof(Calendar), new FrameworkPropertyMetadata(KeyboardNavigationMode.Contained));
LanguageProperty.OverrideMetadata(typeof(Calendar), new FrameworkPropertyMetadata(new PropertyChangedCallback(OnLanguageChanged)));
EventManager.RegisterClassHandler(typeof(Calendar), UIElement.GotFocusEvent, new RoutedEventHandler(OnGotFocus));
}
///
/// Initializes a new instance of the Calendar class.
///
public Calendar()
{
this._blackoutDates = new CalendarBlackoutDatesCollection(this);
this._selectedDates = new SelectedDatesCollection(this);
this.SetCurrentValueInternal(DisplayDateProperty, DateTime.Today);
}
#region Public Properties
#region BlackoutDates
///
/// Gets or sets the dates that are not selectable.
///
public CalendarBlackoutDatesCollection BlackoutDates
{
get { return _blackoutDates; }
}
#endregion BlackoutDates
#region CalendarButtonStyle
///
/// Gets or sets the style for displaying a CalendarButton.
///
public Style CalendarButtonStyle
{
get { return (Style)GetValue(CalendarButtonStyleProperty); }
set { SetValue(CalendarButtonStyleProperty, value); }
}
///
/// Identifies the CalendarButtonStyle dependency property.
///
public static readonly DependencyProperty CalendarButtonStyleProperty =
DependencyProperty.Register(
"CalendarButtonStyle",
typeof(Style),
typeof(Calendar));
#endregion CalendarButtonStyle
#region CalendarDayButtonStyle
///
/// Gets or sets the style for displaying a day.
///
public Style CalendarDayButtonStyle
{
get { return (Style)GetValue(CalendarDayButtonStyleProperty); }
set { SetValue(CalendarDayButtonStyleProperty, value); }
}
///
/// Identifies the DayButtonStyle dependency property.
///
public static readonly DependencyProperty CalendarDayButtonStyleProperty =
DependencyProperty.Register(
"CalendarDayButtonStyle",
typeof(Style),
typeof(Calendar));
#endregion CalendarDayButtonStyle
#region CalendarItemStyle
///
/// Gets or sets the style for a Month.
///
public Style CalendarItemStyle
{
get { return (Style)GetValue(CalendarItemStyleProperty); }
set { SetValue(CalendarItemStyleProperty, value); }
}
///
/// Identifies the MonthStyle dependency property.
///
public static readonly DependencyProperty CalendarItemStyleProperty =
DependencyProperty.Register(
"CalendarItemStyle",
typeof(Style),
typeof(Calendar));
#endregion CalendarItemStyle
#region DisplayDate
///
/// Gets or sets the date to display.
///
///
public DateTime DisplayDate
{
get { return (DateTime)GetValue(DisplayDateProperty); }
set { SetValue(DisplayDateProperty, value); }
}
///
/// Identifies the DisplayDate dependency property.
///
public static readonly DependencyProperty DisplayDateProperty =
DependencyProperty.Register(
"DisplayDate",
typeof(DateTime),
typeof(Calendar),
new FrameworkPropertyMetadata(DateTime.MinValue, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDisplayDateChanged, CoerceDisplayDate));
///
/// DisplayDateProperty property changed handler.
///
/// Calendar that changed its DisplayDate.
/// DependencyPropertyChangedEventArgs.
private static void OnDisplayDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Calendar c = d as Calendar;
Debug.Assert(c != null);
c.DisplayDateInternal = DateTimeHelper.DiscardDayTime((DateTime)e.NewValue);
c.UpdateCellItems();
c.OnDisplayDateChanged(new CalendarDateChangedEventArgs((DateTime)e.OldValue, (DateTime)e.NewValue));
}
private static object CoerceDisplayDate(DependencyObject d, object value)
{
Calendar c = d as Calendar;
DateTime date = (DateTime)value;
if (c.DisplayDateStart.HasValue && (date < c.DisplayDateStart.Value))
{
value = c.DisplayDateStart.Value;
}
else if (c.DisplayDateEnd.HasValue && (date > c.DisplayDateEnd.Value))
{
value = c.DisplayDateEnd.Value;
}
return value;
}
#endregion DisplayDate
#region DisplayDateEnd
///
/// Gets or sets the last date to be displayed.
///
///
public DateTime? DisplayDateEnd
{
get { return (DateTime?)GetValue(DisplayDateEndProperty); }
set { SetValue(DisplayDateEndProperty, value); }
}
///
/// Identifies the DisplayDateEnd dependency property.
///
public static readonly DependencyProperty DisplayDateEndProperty =
DependencyProperty.Register(
"DisplayDateEnd",
typeof(DateTime?),
typeof(Calendar),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDisplayDateEndChanged, CoerceDisplayDateEnd));
///
/// DisplayDateEndProperty property changed handler.
///
/// Calendar that changed its DisplayDateEnd.
/// DependencyPropertyChangedEventArgs.
private static void OnDisplayDateEndChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Calendar c = d as Calendar;
Debug.Assert(c != null);
c.CoerceValue(DisplayDateProperty);
c.UpdateCellItems();
}
private static object CoerceDisplayDateEnd(DependencyObject d, object value)
{
Calendar c = d as Calendar;
DateTime? date = (DateTime?)value;
if (date.HasValue)
{
if (c.DisplayDateStart.HasValue && (date.Value < c.DisplayDateStart.Value))
{
value = c.DisplayDateStart;
}
DateTime? maxSelectedDate = c.SelectedDates.MaximumDate;
if (maxSelectedDate.HasValue && (date.Value < maxSelectedDate.Value))
{
value = maxSelectedDate;
}
}
return value;
}
#endregion DisplayDateEnd
#region DisplayDateStart
///
/// Gets or sets the first date to be displayed.
///
///
public DateTime? DisplayDateStart
{
get { return (DateTime?)GetValue(DisplayDateStartProperty); }
set { SetValue(DisplayDateStartProperty, value); }
}
///
/// Identifies the DisplayDateStart dependency property.
///
public static readonly DependencyProperty DisplayDateStartProperty =
DependencyProperty.Register(
"DisplayDateStart",
typeof(DateTime?),
typeof(Calendar),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDisplayDateStartChanged, CoerceDisplayDateStart));
///
/// DisplayDateStartProperty property changed handler.
///
/// Calendar that changed its DisplayDateStart.
/// DependencyPropertyChangedEventArgs.
private static void OnDisplayDateStartChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Calendar c = d as Calendar;
Debug.Assert(c != null);
c.CoerceValue(DisplayDateEndProperty);
c.CoerceValue(DisplayDateProperty);
c.UpdateCellItems();
}
private static object CoerceDisplayDateStart(DependencyObject d, object value)
{
Calendar c = d as Calendar;
DateTime? date = (DateTime?)value;
if (date.HasValue)
{
DateTime? minSelectedDate = c.SelectedDates.MinimumDate;
if (minSelectedDate.HasValue && (date.Value > minSelectedDate.Value))
{
value = minSelectedDate;
}
}
return value;
}
#endregion DisplayDateStart
#region DisplayMode
///
/// Gets or sets a value indicating whether the calendar is displayed in months or years.
///
public CalendarMode DisplayMode
{
get { return (CalendarMode)GetValue(DisplayModeProperty); }
set { SetValue(DisplayModeProperty, value); }
}
///
/// Identifies the DisplayMode dependency property.
///
public static readonly DependencyProperty DisplayModeProperty =
DependencyProperty.Register(
"DisplayMode",
typeof(CalendarMode),
typeof(Calendar),
new FrameworkPropertyMetadata(CalendarMode.Month, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDisplayModePropertyChanged),
new ValidateValueCallback(IsValidDisplayMode));
///
/// DisplayModeProperty property changed handler.
///
/// Calendar that changed its DisplayMode.
/// DependencyPropertyChangedEventArgs.
private static void OnDisplayModePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Calendar c = d as Calendar;
Debug.Assert(c != null);
CalendarMode mode = (CalendarMode)e.NewValue;
CalendarMode oldMode = (CalendarMode)e.OldValue;
CalendarItem monthControl = c.MonthControl;
switch (mode)
{
case CalendarMode.Month:
{
if (oldMode == CalendarMode.Year || oldMode == CalendarMode.Decade)
{
// Cancel highlight when switching to month display mode
c.HoverStart = c.HoverEnd = null;
c.CurrentDate = c.DisplayDate;
}
c.UpdateCellItems();
break;
}
case CalendarMode.Year:
case CalendarMode.Decade:
if (oldMode == CalendarMode.Month)
{
c.SetCurrentValueInternal(DisplayDateProperty, c.CurrentDate);
}
c.UpdateCellItems();
break;
default:
Debug.Assert(false);
break;
}
c.OnDisplayModeChanged(new CalendarModeChangedEventArgs((CalendarMode)e.OldValue, mode));
}
#endregion DisplayMode
#region FirstDayOfWeek
///
/// Gets or sets the day that is considered the beginning of the week.
///
public DayOfWeek FirstDayOfWeek
{
get { return (DayOfWeek)GetValue(FirstDayOfWeekProperty); }
set { SetValue(FirstDayOfWeekProperty, value); }
}
///
/// Identifies the FirstDayOfWeek dependency property.
///
public static readonly DependencyProperty FirstDayOfWeekProperty =
DependencyProperty.Register(
"FirstDayOfWeek",
typeof(DayOfWeek),
typeof(Calendar),
new FrameworkPropertyMetadata(DateTimeHelper.GetCurrentDateFormat().FirstDayOfWeek,
OnFirstDayOfWeekChanged),
new ValidateValueCallback(IsValidFirstDayOfWeek));
///
/// FirstDayOfWeekProperty property changed handler.
///
/// Calendar that changed its FirstDayOfWeek.
/// DependencyPropertyChangedEventArgs.
private static void OnFirstDayOfWeekChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Calendar c = d as Calendar;
c.UpdateCellItems();
}
#endregion FirstDayOfWeek
#region IsTodayHighlighted
///
/// Gets or sets a value indicating whether the current date is highlighted.
///
public bool IsTodayHighlighted
{
get { return (bool)GetValue(IsTodayHighlightedProperty); }
set { SetValue(IsTodayHighlightedProperty, value); }
}
///
/// Identifies the IsTodayHighlighted dependency property.
///
public static readonly DependencyProperty IsTodayHighlightedProperty =
DependencyProperty.Register(
"IsTodayHighlighted",
typeof(bool),
typeof(Calendar),
new FrameworkPropertyMetadata(true, OnIsTodayHighlightedChanged));
///
/// IsTodayHighlightedProperty property changed handler.
///
/// Calendar that changed its IsTodayHighlighted.
/// DependencyPropertyChangedEventArgs.
private static void OnIsTodayHighlightedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Calendar c = d as Calendar;
int i = DateTimeHelper.CompareYearMonth(c.DisplayDateInternal, DateTime.Today);
if (i > -2 && i < 2)
{
c.UpdateCellItems();
}
}
#endregion IsTodayHighlighted
#region Language
private static void OnLanguageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Calendar c = d as Calendar;
if (DependencyPropertyHelper.GetValueSource(d, Calendar.FirstDayOfWeekProperty).BaseValueSource == BaseValueSource.Default)
{
c.SetCurrentValueInternal(FirstDayOfWeekProperty, DateTimeHelper.GetDateFormat(DateTimeHelper.GetCulture(c)).FirstDayOfWeek);
c.UpdateCellItems();
}
}
#endregion
#region SelectedDate
///
/// Gets or sets the currently selected date.
///
///
public DateTime? SelectedDate
{
get { return (DateTime?)GetValue(SelectedDateProperty); }
set { SetValue(SelectedDateProperty, value); }
}
///
/// Identifies the SelectedDate dependency property.
///
public static readonly DependencyProperty SelectedDateProperty =
DependencyProperty.Register(
"SelectedDate",
typeof(DateTime?),
typeof(Calendar),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedDateChanged));
///
/// SelectedDateProperty property changed handler.
///
/// Calendar that changed its SelectedDate.
/// DependencyPropertyChangedEventArgs.
private static void OnSelectedDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Calendar c = d as Calendar;
Debug.Assert(c != null);
if (c.SelectionMode != CalendarSelectionMode.None || e.NewValue == null)
{
DateTime? addedDate;
addedDate = (DateTime?)e.NewValue;
if (IsValidDateSelection(c, addedDate))
{
if (!addedDate.HasValue)
{
c.SelectedDates.ClearInternal(true /*fireChangeNotification*/);
}
else
{
if (addedDate.HasValue && !(c.SelectedDates.Count > 0 && c.SelectedDates[0] == addedDate.Value))
{
c.SelectedDates.ClearInternal();
c.SelectedDates.Add(addedDate.Value);
}
}
// We update the current date for only the Single mode.For the other modes it automatically gets updated
if (c.SelectionMode == CalendarSelectionMode.SingleDate)
{
if (addedDate.HasValue)
{
c.CurrentDate = addedDate.Value;
}
c.UpdateCellItems();
}
}
else
{
throw new ArgumentOutOfRangeException("d", SR.Get(SRID.Calendar_OnSelectedDateChanged_InvalidValue));
}
}
else
{
throw new InvalidOperationException(SR.Get(SRID.Calendar_OnSelectedDateChanged_InvalidOperation));
}
}
#endregion SelectedDate
#region SelectedDates
//
///
/// Gets the dates that are currently selected.
///
public SelectedDatesCollection SelectedDates
{
get { return _selectedDates; }
}
#endregion SelectedDates
#region SelectionMode
///
/// Gets or sets the selection mode for the calendar.
///
public CalendarSelectionMode SelectionMode
{
get { return (CalendarSelectionMode)GetValue(SelectionModeProperty); }
set { SetValue(SelectionModeProperty, value); }
}
///
/// Identifies the SelectionMode dependency property.
///
public static readonly DependencyProperty SelectionModeProperty =
DependencyProperty.Register(
"SelectionMode",
typeof(CalendarSelectionMode),
typeof(Calendar),
new FrameworkPropertyMetadata(CalendarSelectionMode.SingleDate, OnSelectionModeChanged),
new ValidateValueCallback(IsValidSelectionMode));
private static void OnSelectionModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Calendar c = d as Calendar;
Debug.Assert(c != null);
c.HoverStart = c.HoverEnd = null;
c.SelectedDates.ClearInternal(true /*fireChangeNotification*/);
c.OnSelectionModeChanged(EventArgs.Empty);
}
#endregion SelectionMode
#endregion Public Properties
#region Internal Events
internal event MouseButtonEventHandler DayButtonMouseUp;
internal event RoutedEventHandler DayOrMonthPreviewKeyDown;
#endregion Internal Events
#region Internal Properties
///
/// This flag is used to determine whether DatePicker should change its
/// DisplayDate because of a SelectedDate change on its Calendar
///
internal bool DatePickerDisplayDateFlag
{
get;
set;
}
internal DateTime DisplayDateInternal
{
get;
private set;
}
internal DateTime DisplayDateEndInternal
{
get
{
return this.DisplayDateEnd.GetValueOrDefault(DateTime.MaxValue);
}
}
internal DateTime DisplayDateStartInternal
{
get
{
return this.DisplayDateStart.GetValueOrDefault(DateTime.MinValue);
}
}
internal DateTime CurrentDate
{
get { return _currentDate.GetValueOrDefault(this.DisplayDateInternal); }
set { _currentDate = value; }
}
internal DateTime? HoverStart
{
get
{
return this.SelectionMode == CalendarSelectionMode.None ? null : _hoverStart;
}
set
{
_hoverStart = value;
}
}
internal DateTime? HoverEnd
{
get
{
return this.SelectionMode == CalendarSelectionMode.None ? null : _hoverEnd;
}
set
{
_hoverEnd = value;
}
}
internal CalendarItem MonthControl
{
get { return _monthControl; }
}
internal DateTime DisplayMonth
{
get
{
return DateTimeHelper.DiscardDayTime(DisplayDate);
}
}
internal DateTime DisplayYear
{
get
{
return new DateTime(DisplayDate.Year, 1, 1);
}
}
#endregion Internal Properties
#region Private Properties
#endregion Private Properties
#region Public Methods
///
/// Invoked whenever application code or an internal process,
/// such as a rebuilding layout pass, calls the ApplyTemplate method.
///
public override void OnApplyTemplate()
{
if (_monthControl != null)
{
_monthControl.Owner = null;
}
base.OnApplyTemplate();
_monthControl = GetTemplateChild(ElementMonth) as CalendarItem;
if (_monthControl != null)
{
_monthControl.Owner = this;
}
this.CurrentDate = this.DisplayDate;
UpdateCellItems();
}
///
/// Provides a text representation of the selected date.
///
/// A text representation of the selected date, or an empty string if SelectedDate is a null reference.
public override string ToString()
{
if (this.SelectedDate != null)
{
return this.SelectedDate.Value.ToString(DateTimeHelper.GetDateFormat(DateTimeHelper.GetCulture(this)));
}
else
{
return string.Empty;
}
}
#endregion Public Methods
#region Protected Methods
protected virtual void OnSelectedDatesChanged(SelectionChangedEventArgs e)
{
RaiseEvent(e);
}
protected virtual void OnDisplayDateChanged(CalendarDateChangedEventArgs e)
{
EventHandler handler = this.DisplayDateChanged;
if (handler != null)
{
handler(this, e);
}
}
protected virtual void OnDisplayModeChanged(CalendarModeChangedEventArgs e)
{
EventHandler handler = this.DisplayModeChanged;
if (handler != null)
{
handler(this, e);
}
}
protected virtual void OnSelectionModeChanged(EventArgs e)
{
EventHandler handler = this.SelectionModeChanged;
if (handler != null)
{
handler(this, e);
}
}
///
/// Creates the automation peer for this Calendar Control.
///
///
protected override AutomationPeer OnCreateAutomationPeer()
{
return new CalendarAutomationPeer(this);
}
protected override void OnKeyDown(KeyEventArgs e)
{
if (!e.Handled)
{
e.Handled = ProcessCalendarKey(e);
}
}
protected override void OnKeyUp(KeyEventArgs e)
{
if (!e.Handled)
{
if (e.Key == Key.LeftShift || e.Key == Key.RightShift)
{
ProcessShiftKeyUp();
}
}
}
#endregion Protected Methods
#region Internal Methods
internal CalendarDayButton FindDayButtonFromDay(DateTime day)
{
if (this.MonthControl != null)
{
foreach (CalendarDayButton b in this.MonthControl.GetCalendarDayButtons())
{
if (b.DataContext is DateTime)
{
if (DateTimeHelper.CompareDays((DateTime)b.DataContext, day) == 0)
{
return b;
}
}
}
}
return null;
}
internal static bool IsValidDateSelection(Calendar cal, object value)
{
return (value == null) || (!cal.BlackoutDates.Contains((DateTime)value));
}
internal void OnDayButtonMouseUp(MouseButtonEventArgs e)
{
MouseButtonEventHandler handler = this.DayButtonMouseUp;
if (null != handler)
{
handler(this, e);
}
}
internal void OnDayOrMonthPreviewKeyDown(RoutedEventArgs e)
{
RoutedEventHandler handler = this.DayOrMonthPreviewKeyDown;
if (null != handler)
{
handler(this, e);
}
}
// If the day is a trailing day, Update the DisplayDate
internal void OnDayClick(DateTime selectedDate)
{
if (this.SelectionMode == CalendarSelectionMode.None)
{
this.CurrentDate = selectedDate;
}
if (DateTimeHelper.CompareYearMonth(selectedDate, this.DisplayDateInternal) != 0)
{
MoveDisplayTo(selectedDate);
}
else
{
UpdateCellItems();
FocusDate(selectedDate);
}
}
internal void OnCalendarButtonPressed(CalendarButton b, bool switchDisplayMode)
{
if (b.DataContext is DateTime)
{
DateTime d = (DateTime)b.DataContext;
DateTime? newDate = null;
CalendarMode newMode = CalendarMode.Month;
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
Debug.Assert(false);
break;
}
case CalendarMode.Year:
{
newDate = DateTimeHelper.SetYearMonth(this.DisplayDate, d);
newMode = CalendarMode.Month;
break;
}
case CalendarMode.Decade:
{
newDate = DateTimeHelper.SetYear(this.DisplayDate, d.Year);
newMode = CalendarMode.Year;
break;
}
default:
Debug.Assert(false);
break;
}
if (newDate.HasValue)
{
this.DisplayDate = newDate.Value;
if (switchDisplayMode)
{
this.SetCurrentValueInternal(DisplayModeProperty, newMode);
FocusDate(this.DisplayMode == CalendarMode.Month ? this.CurrentDate : this.DisplayDate);
}
}
}
}
private DateTime? GetDateOffset(DateTime date, int offset, CalendarMode displayMode)
{
DateTime? result = null;
switch (displayMode)
{
case CalendarMode.Month:
{
result = DateTimeHelper.AddMonths(date, offset);
break;
}
case CalendarMode.Year:
{
result = DateTimeHelper.AddYears(date, offset);
break;
}
case CalendarMode.Decade:
{
result = DateTimeHelper.AddYears(this.DisplayDate, offset * YEARS_PER_DECADE);
break;
}
default:
Debug.Assert(false);
break;
}
return result;
}
private void MoveDisplayTo(DateTime? date)
{
if (date.HasValue)
{
DateTime d = date.Value.Date;
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
this.SetCurrentValueInternal(DisplayDateProperty, DateTimeHelper.DiscardDayTime(d));
this.CurrentDate = d;
UpdateCellItems();
break;
}
case CalendarMode.Year:
case CalendarMode.Decade:
{
this.SetCurrentValueInternal(DisplayDateProperty, d);
UpdateCellItems();
break;
}
default:
Debug.Assert(false);
break;
}
FocusDate(d);
}
}
internal void OnNextClick()
{
DateTime? nextDate = GetDateOffset(this.DisplayDate, 1, this.DisplayMode);
if (nextDate.HasValue)
{
MoveDisplayTo(DateTimeHelper.DiscardDayTime(nextDate.Value));
}
}
internal void OnPreviousClick()
{
DateTime? nextDate = GetDateOffset(this.DisplayDate, -1, this.DisplayMode);
if (nextDate.HasValue)
{
MoveDisplayTo(DateTimeHelper.DiscardDayTime(nextDate.Value));
}
}
internal void OnSelectedDatesCollectionChanged(SelectionChangedEventArgs e)
{
if (IsSelectionChanged(e))
{
if (AutomationPeer.ListenerExists(AutomationEvents.SelectionItemPatternOnElementSelected) ||
AutomationPeer.ListenerExists(AutomationEvents.SelectionItemPatternOnElementAddedToSelection) ||
AutomationPeer.ListenerExists(AutomationEvents.SelectionItemPatternOnElementRemovedFromSelection))
{
CalendarAutomationPeer peer = FrameworkElementAutomationPeer.FromElement(this) as CalendarAutomationPeer;
if (peer != null)
{
peer.RaiseSelectionEvents(e);
}
}
CoerceFromSelection();
OnSelectedDatesChanged(e);
}
}
internal void UpdateCellItems()
{
CalendarItem monthControl = this.MonthControl;
if (monthControl != null)
{
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
monthControl.UpdateMonthMode();
break;
}
case CalendarMode.Year:
{
monthControl.UpdateYearMode();
break;
}
case CalendarMode.Decade:
{
monthControl.UpdateDecadeMode();
break;
}
default:
Debug.Assert(false);
break;
}
}
}
#endregion Internal Methods
#region Private Methods
private void CoerceFromSelection()
{
CoerceValue(DisplayDateStartProperty);
CoerceValue(DisplayDateEndProperty);
CoerceValue(DisplayDateProperty);
}
// This method adds the days that were selected by Keyboard to the SelectedDays Collection
private void AddKeyboardSelection()
{
if (this.HoverStart != null)
{
this.SelectedDates.ClearInternal();
// In keyboard selection, we are sure that the collection does not include any blackout days
this.SelectedDates.AddRange(this.HoverStart.Value, this.CurrentDate);
}
}
private static bool IsSelectionChanged(SelectionChangedEventArgs e)
{
if (e.AddedItems.Count != e.RemovedItems.Count)
{
return true;
}
foreach (DateTime addedDate in e.AddedItems)
{
if (!e.RemovedItems.Contains(addedDate))
{
return true;
}
}
return false;
}
private static bool IsValidDisplayMode(object value)
{
CalendarMode mode = (CalendarMode)value;
return mode == CalendarMode.Month
|| mode == CalendarMode.Year
|| mode == CalendarMode.Decade;
}
internal static bool IsValidFirstDayOfWeek(object value)
{
DayOfWeek day = (DayOfWeek)value;
return day == DayOfWeek.Sunday
|| day == DayOfWeek.Monday
|| day == DayOfWeek.Tuesday
|| day == DayOfWeek.Wednesday
|| day == DayOfWeek.Thursday
|| day == DayOfWeek.Friday
|| day == DayOfWeek.Saturday;
}
private static bool IsValidKeyboardSelection(Calendar cal, object value)
{
if (value == null)
{
return true;
}
else
{
if (cal.BlackoutDates.Contains((DateTime)value))
{
return false;
}
else
{
return DateTime.Compare((DateTime)value, cal.DisplayDateStartInternal) >= 0 && DateTime.Compare((DateTime)value, cal.DisplayDateEndInternal) <= 0;
}
}
}
private static bool IsValidSelectionMode(object value)
{
CalendarSelectionMode mode = (CalendarSelectionMode)value;
return mode == CalendarSelectionMode.SingleDate
|| mode == CalendarSelectionMode.SingleRange
|| mode == CalendarSelectionMode.MultipleRange
|| mode == CalendarSelectionMode.None;
}
private void OnSelectedMonthChanged(DateTime? selectedMonth)
{
if (selectedMonth.HasValue)
{
Debug.Assert(this.DisplayMode == CalendarMode.Year);
this.SetCurrentValueInternal(DisplayDateProperty, selectedMonth.Value);
UpdateCellItems();
FocusDate(selectedMonth.Value);
}
}
private void OnSelectedYearChanged(DateTime? selectedYear)
{
if (selectedYear.HasValue)
{
Debug.Assert(this.DisplayMode == CalendarMode.Decade);
this.SetCurrentValueInternal(DisplayDateProperty, selectedYear.Value);
UpdateCellItems();
FocusDate(selectedYear.Value);
}
}
internal void FocusDate(DateTime date)
{
if (MonthControl != null)
{
MonthControl.FocusDate(date);
}
}
///
/// Called when this element gets focus.
///
private static void OnGotFocus(object sender, RoutedEventArgs e)
{
// When Calendar gets focus move it to the DisplayDate
var c = (Calendar)sender;
if (!e.Handled && e.OriginalSource == c)
{
// This check is for the case where the DisplayDate is the first of the month
// and the SelectedDate is in the middle of the month. If you tab into the Calendar
// the focus should go to the SelectedDate, not the DisplayDate.
if (c.SelectedDate.HasValue && DateTimeHelper.CompareYearMonth(c.SelectedDate.Value, c.DisplayDateInternal) == 0)
{
c.FocusDate(c.SelectedDate.Value);
}
else
{
c.FocusDate(c.DisplayDate);
}
e.Handled = true;
}
}
private bool ProcessCalendarKey(KeyEventArgs e)
{
if (this.DisplayMode == CalendarMode.Month)
{
// If a blackout day is inactive, when clicked on it, the previous inactive day which is not a blackout day can get the focus.
// In this case we should allow keyboard functions on that inactive day
CalendarDayButton currentDayButton = (MonthControl != null) ? MonthControl.GetCalendarDayButton(this.CurrentDate) : null;
if (DateTimeHelper.CompareYearMonth(this.CurrentDate, this.DisplayDateInternal) != 0 && currentDayButton != null && !currentDayButton.IsInactive)
{
return false;
}
}
bool ctrl, shift;
CalendarKeyboardHelper.GetMetaKeyState(out ctrl, out shift);
switch (e.Key)
{
case Key.Up:
{
ProcessUpKey(ctrl, shift);
return true;
}
case Key.Down:
{
ProcessDownKey(ctrl, shift);
return true;
}
case Key.Left:
{
ProcessLeftKey(shift);
return true;
}
case Key.Right:
{
ProcessRightKey(shift);
return true;
}
case Key.PageDown:
{
ProcessPageDownKey(shift);
return true;
}
case Key.PageUp:
{
ProcessPageUpKey(shift);
return true;
}
case Key.Home:
{
ProcessHomeKey(shift);
return true;
}
case Key.End:
{
ProcessEndKey(shift);
return true;
}
case Key.Enter:
case Key.Space:
{
return ProcessEnterKey();
}
}
return false;
}
private void ProcessDownKey(bool ctrl, bool shift)
{
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
if (!ctrl || shift)
{
DateTime? selectedDate = this._blackoutDates.GetNonBlackoutDate(DateTimeHelper.AddDays(this.CurrentDate, COLS), 1);
ProcessSelection(shift, selectedDate);
}
break;
}
case CalendarMode.Year:
{
if (ctrl)
{
this.SetCurrentValueInternal(DisplayModeProperty, CalendarMode.Month);
FocusDate(this.DisplayDate);
}
else
{
DateTime? selectedMonth = DateTimeHelper.AddMonths(this.DisplayDate, YEAR_COLS);
OnSelectedMonthChanged(selectedMonth);
}
break;
}
case CalendarMode.Decade:
{
if (ctrl)
{
this.SetCurrentValueInternal(DisplayModeProperty, CalendarMode.Year);
FocusDate(this.DisplayDate);
}
else
{
DateTime? selectedYear = DateTimeHelper.AddYears(this.DisplayDate, YEAR_COLS);
OnSelectedYearChanged(selectedYear);
}
break;
}
}
}
private void ProcessEndKey(bool shift)
{
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
if (this.DisplayDate != null)
{
DateTime? selectedDate = new DateTime(this.DisplayDateInternal.Year, this.DisplayDateInternal.Month, 1);
if (DateTimeHelper.CompareYearMonth(DateTime.MaxValue, selectedDate.Value) > 0)
{
// since DisplayDate is not equal to DateTime.MaxValue we are sure selectedDate is not null
selectedDate = DateTimeHelper.AddMonths(selectedDate.Value, 1).Value;
selectedDate = DateTimeHelper.AddDays(selectedDate.Value, -1).Value;
}
else
{
selectedDate = DateTime.MaxValue;
}
ProcessSelection(shift, selectedDate);
}
break;
}
case CalendarMode.Year:
{
DateTime selectedMonth = new DateTime(this.DisplayDate.Year, 12, 1);
OnSelectedMonthChanged(selectedMonth);
break;
}
case CalendarMode.Decade:
{
DateTime? selectedYear = new DateTime(DateTimeHelper.EndOfDecade(this.DisplayDate), 1, 1);
OnSelectedYearChanged(selectedYear);
break;
}
}
}
private bool ProcessEnterKey()
{
switch (this.DisplayMode)
{
case CalendarMode.Year:
{
this.SetCurrentValueInternal(DisplayModeProperty, CalendarMode.Month);
FocusDate(this.DisplayDate);
return true;
}
case CalendarMode.Decade:
{
this.SetCurrentValueInternal(DisplayModeProperty, CalendarMode.Year);
FocusDate(this.DisplayDate);
return true;
}
}
return false;
}
private void ProcessHomeKey(bool shift)
{
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
//
DateTime? selectedDate = new DateTime(this.DisplayDateInternal.Year, this.DisplayDateInternal.Month, 1);
ProcessSelection(shift, selectedDate);
break;
}
case CalendarMode.Year:
{
DateTime selectedMonth = new DateTime(this.DisplayDate.Year, 1, 1);
OnSelectedMonthChanged(selectedMonth);
break;
}
case CalendarMode.Decade:
{
DateTime? selectedYear = new DateTime(DateTimeHelper.DecadeOfDate(this.DisplayDate), 1, 1);
OnSelectedYearChanged(selectedYear);
break;
}
}
}
private void ProcessLeftKey(bool shift)
{
int moveAmmount = (!this.IsRightToLeft) ? -1 : 1;
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
DateTime? selectedDate = this._blackoutDates.GetNonBlackoutDate(DateTimeHelper.AddDays(this.CurrentDate, moveAmmount), moveAmmount);
ProcessSelection(shift, selectedDate);
break;
}
case CalendarMode.Year:
{
DateTime? selectedMonth = DateTimeHelper.AddMonths(this.DisplayDate, moveAmmount);
OnSelectedMonthChanged(selectedMonth);
break;
}
case CalendarMode.Decade:
{
DateTime? selectedYear = DateTimeHelper.AddYears(this.DisplayDate, moveAmmount);
OnSelectedYearChanged(selectedYear);
break;
}
}
}
private void ProcessPageDownKey(bool shift)
{
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
DateTime? selectedDate = this._blackoutDates.GetNonBlackoutDate(DateTimeHelper.AddMonths(this.CurrentDate, 1), 1);
ProcessSelection(shift, selectedDate);
break;
}
case CalendarMode.Year:
{
DateTime? selectedMonth = DateTimeHelper.AddYears(this.DisplayDate, 1);
OnSelectedMonthChanged(selectedMonth);
break;
}
case CalendarMode.Decade:
{
DateTime? selectedYear = DateTimeHelper.AddYears(this.DisplayDate, 10 );
OnSelectedYearChanged(selectedYear);
break;
}
}
}
private void ProcessPageUpKey(bool shift)
{
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
DateTime? selectedDate = this._blackoutDates.GetNonBlackoutDate(DateTimeHelper.AddMonths(this.CurrentDate, -1), -1);
ProcessSelection(shift, selectedDate);
break;
}
case CalendarMode.Year:
{
DateTime? selectedMonth = DateTimeHelper.AddYears(this.DisplayDate, -1);
OnSelectedMonthChanged(selectedMonth);
break;
}
case CalendarMode.Decade:
{
DateTime? selectedYear = DateTimeHelper.AddYears(this.DisplayDate, -10);
OnSelectedYearChanged(selectedYear);
break;
}
}
}
private void ProcessRightKey(bool shift)
{
int moveAmmount = (!this.IsRightToLeft) ? 1 : -1;
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
DateTime? selectedDate = this._blackoutDates.GetNonBlackoutDate(DateTimeHelper.AddDays(this.CurrentDate, moveAmmount), moveAmmount);
ProcessSelection(shift, selectedDate);
break;
}
case CalendarMode.Year:
{
DateTime? selectedMonth = DateTimeHelper.AddMonths(this.DisplayDate, moveAmmount);
OnSelectedMonthChanged(selectedMonth);
break;
}
case CalendarMode.Decade:
{
DateTime? selectedYear = DateTimeHelper.AddYears(this.DisplayDate, moveAmmount);
OnSelectedYearChanged(selectedYear);
break;
}
}
}
private void ProcessSelection(bool shift, DateTime? lastSelectedDate)
{
if (this.SelectionMode == CalendarSelectionMode.None && lastSelectedDate != null)
{
OnDayClick(lastSelectedDate.Value);
return;
}
if (lastSelectedDate != null && IsValidKeyboardSelection(this, lastSelectedDate.Value))
{
if (this.SelectionMode == CalendarSelectionMode.SingleRange || this.SelectionMode == CalendarSelectionMode.MultipleRange)
{
this.SelectedDates.ClearInternal();
if (shift)
{
this._isShiftPressed = true;
if (!this.HoverStart.HasValue)
{
this.HoverStart = this.HoverEnd = this.CurrentDate;
}
// If we hit a BlackOutDay with keyboard we do not update the HoverEnd
CalendarDateRange range;
if (DateTime.Compare(this.HoverStart.Value, lastSelectedDate.Value) < 0)
{
range = new CalendarDateRange(this.HoverStart.Value, lastSelectedDate.Value);
}
else
{
range = new CalendarDateRange(lastSelectedDate.Value, this.HoverStart.Value);
}
if (!this.BlackoutDates.ContainsAny(range))
{
this._currentDate = lastSelectedDate;
this.HoverEnd = lastSelectedDate;
}
OnDayClick(this.CurrentDate);
}
else
{
this.HoverStart = this.HoverEnd = this.CurrentDate = lastSelectedDate.Value;
AddKeyboardSelection();
OnDayClick(lastSelectedDate.Value);
}
}
else
{
// ON CLEAR
this.CurrentDate = lastSelectedDate.Value;
this.HoverStart = this.HoverEnd = null;
if (this.SelectedDates.Count > 0)
{
this.SelectedDates[0] = lastSelectedDate.Value;
}
else
{
this.SelectedDates.Add(lastSelectedDate.Value);
}
OnDayClick(lastSelectedDate.Value);
}
UpdateCellItems();
}
}
private void ProcessShiftKeyUp()
{
if (this._isShiftPressed && (this.SelectionMode == CalendarSelectionMode.SingleRange || this.SelectionMode == CalendarSelectionMode.MultipleRange))
{
AddKeyboardSelection();
this._isShiftPressed = false;
this.HoverStart = this.HoverEnd = null;
}
}
private void ProcessUpKey(bool ctrl, bool shift)
{
switch (this.DisplayMode)
{
case CalendarMode.Month:
{
if (ctrl)
{
this.SetCurrentValueInternal(DisplayModeProperty, CalendarMode.Year);
FocusDate(this.DisplayDate);
}
else
{
DateTime? selectedDate = this._blackoutDates.GetNonBlackoutDate(DateTimeHelper.AddDays(this.CurrentDate, -COLS), -1);
ProcessSelection(shift, selectedDate);
}
break;
}
case CalendarMode.Year:
{
if (ctrl)
{
this.SetCurrentValueInternal(DisplayModeProperty, CalendarMode.Decade);
FocusDate(this.DisplayDate);
}
else
{
DateTime? selectedMonth = DateTimeHelper.AddMonths(this.DisplayDate, -YEAR_COLS);
OnSelectedMonthChanged(selectedMonth);
}
break;
}
case CalendarMode.Decade:
{
if (!ctrl)
{
DateTime? selectedYear = DateTimeHelper.AddYears(this.DisplayDate, -YEAR_COLS);
OnSelectedYearChanged(selectedYear);
}
break;
}
}
}
#endregion Private Methods
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- BindingCollection.cs
- DataGridViewHitTestInfo.cs
- CompositeControl.cs
- ComplexObject.cs
- Assembly.cs
- EventListener.cs
- ParserOptions.cs
- FunctionQuery.cs
- FolderBrowserDialogDesigner.cs
- ContentElementAutomationPeer.cs
- ProjectionPlanCompiler.cs
- Misc.cs
- MLangCodePageEncoding.cs
- SqlMultiplexer.cs
- FtpWebResponse.cs
- CodeChecksumPragma.cs
- DateTimeSerializationSection.cs
- WebPartEditorCancelVerb.cs
- Int32AnimationBase.cs
- MonthChangedEventArgs.cs
- HwndSubclass.cs
- ColorConvertedBitmapExtension.cs
- TdsParserStaticMethods.cs
- DesignerToolStripControlHost.cs
- BulletDecorator.cs
- XPathNavigatorKeyComparer.cs
- IdleTimeoutMonitor.cs
- GatewayIPAddressInformationCollection.cs
- X509SecurityTokenProvider.cs
- DynamicValueConverter.cs
- FunctionCommandText.cs
- mda.cs
- WSFederationHttpBindingElement.cs
- TranslateTransform3D.cs
- ContextQuery.cs
- OleDbErrorCollection.cs
- GlyphManager.cs
- SystemIPInterfaceProperties.cs
- NotifyCollectionChangedEventArgs.cs
- DataGridHelper.cs
- SaveFileDialogDesigner.cs
- XPathNodeList.cs
- ReflectionHelper.cs
- PeerNameRecord.cs
- SmtpReplyReader.cs
- LiteralText.cs
- PerformanceCounterNameAttribute.cs
- _SslStream.cs
- LiteralTextParser.cs
- ConversionValidationRule.cs
- SqlConnectionManager.cs
- Win32Native.cs
- List.cs
- SecurityContextCookieSerializer.cs
- DesignerToolStripControlHost.cs
- TableStyle.cs
- ServiceModelActivationSectionGroup.cs
- Size3DValueSerializer.cs
- EndPoint.cs
- DesignerSerializerAttribute.cs
- SHA256Managed.cs
- DocComment.cs
- BaseProcessor.cs
- SystemGatewayIPAddressInformation.cs
- DataContractSerializerOperationFormatter.cs
- GeneralTransform2DTo3D.cs
- SoapEnumAttribute.cs
- DESCryptoServiceProvider.cs
- DropAnimation.xaml.cs
- CodeSnippetCompileUnit.cs
- SmtpException.cs
- DataTableClearEvent.cs
- MediaContextNotificationWindow.cs
- DetailsViewInsertedEventArgs.cs
- CompositeActivityCodeGenerator.cs
- PEFileReader.cs
- InvalidBodyAccessException.cs
- ElementFactory.cs
- VisualState.cs
- TypeToken.cs
- PageVisual.cs
- EntityKeyElement.cs
- XmlUtf8RawTextWriter.cs
- MetadataProperty.cs
- DeleteMemberBinder.cs
- EditingCommands.cs
- FormsAuthenticationUserCollection.cs
- HtmlTextArea.cs
- DataStreamFromComStream.cs
- ForEachAction.cs
- SafeNativeMethods.cs
- SHA256.cs
- SpeechSynthesizer.cs
- OdbcRowUpdatingEvent.cs
- Crc32.cs
- UnknownBitmapDecoder.cs
- DataKey.cs
- DecimalKeyFrameCollection.cs
- ColumnMapTranslator.cs
- CorrelationToken.cs