CalendarItem.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / Primitives / CalendarItem.cs / 1305600 / CalendarItem.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
//--------------------------------------------------------------------------- 

using System; 
using System.Collections.Generic; 
using System.Diagnostics;
using System.Globalization; 
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input; 

namespace System.Windows.Controls.Primitives 
{ 
    [TemplatePart(Name = CalendarItem.ElementRoot, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = CalendarItem.ElementHeaderButton, Type = typeof(Button))] 
    [TemplatePart(Name = CalendarItem.ElementPreviousButton, Type = typeof(Button))]
    [TemplatePart(Name = CalendarItem.ElementNextButton, Type = typeof(Button))]
    [TemplatePart(Name = CalendarItem.ElementDayTitleTemplate, Type = typeof(DataTemplate))]
    [TemplatePart(Name = CalendarItem.ElementMonthView, Type = typeof(Grid))] 
    [TemplatePart(Name = CalendarItem.ElementYearView, Type = typeof(Grid))]
    [TemplatePart(Name = CalendarItem.ElementDisabledVisual, Type = typeof(FrameworkElement))] 
    public sealed partial class CalendarItem : Control 
    {
        #region Constants 
        private const string ElementRoot = "PART_Root";
        private const string ElementHeaderButton = "PART_HeaderButton";
        private const string ElementPreviousButton = "PART_PreviousButton";
        private const string ElementNextButton = "PART_NextButton"; 
        private const string ElementDayTitleTemplate = "DayTitleTemplate";
        private const string ElementMonthView = "PART_MonthView"; 
        private const string ElementYearView = "PART_YearView"; 
        private const string ElementDisabledVisual = "PART_DisabledVisual";
 
        private const int COLS = 7;
        private const int ROWS = 7;
        private const int YEAR_COLS = 4;
        private const int YEAR_ROWS = 3; 
        private const int NUMBER_OF_DAYS_IN_WEEK = 7;
 
        #endregion Constants 

        #region Data 

        private static ComponentResourceKey _dayTitleTemplateResourceKey = null;

        private System.Globalization.Calendar _calendar = new GregorianCalendar(); 
        private DataTemplate _dayTitleTemplate;
        private FrameworkElement _disabledVisual; 
        private Button _headerButton; 
        private Grid _monthView;
        private Button _nextButton; 
        private Button _previousButton;
        private Grid _yearView;
        private bool _isMonthPressed;
        private bool _isDayPressed; 

        #endregion Data 
 
        static CalendarItem()
        { 
            DefaultStyleKeyProperty.OverrideMetadata(typeof(CalendarItem), new FrameworkPropertyMetadata(typeof(CalendarItem)));
            FocusableProperty.OverrideMetadata(typeof(CalendarItem), new FrameworkPropertyMetadata(false));
            KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(CalendarItem), new FrameworkPropertyMetadata(KeyboardNavigationMode.Once));
            KeyboardNavigation.DirectionalNavigationProperty.OverrideMetadata(typeof(CalendarItem), new FrameworkPropertyMetadata(KeyboardNavigationMode.Contained)); 

            IsEnabledProperty.OverrideMetadata(typeof(CalendarItem), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); 
        } 

        ///  
        /// Represents the month that is used in Calendar Control.
        /// 
        public CalendarItem()
        { 
        }
 
        #region Internal Properties 

        internal Grid MonthView 
        {
            get { return _monthView; }
        }
 
        internal Calendar Owner
        { 
            get; 
            set;
        } 

        internal Grid YearView
        {
            get { return _yearView; } 
        }
 
        #endregion Internal Properties 

        #region Private Properties 

        /// 
        /// Gets a value indicating whether the calendar is displayed in months, years or decades.
        ///  
        private CalendarMode DisplayMode
        { 
            get 
            {
                return (this.Owner != null) ? this.Owner.DisplayMode : CalendarMode.Month; 
            }
        }

        internal Button HeaderButton 
        {
            get 
            { 
                return this._headerButton;
            } 
        }

        internal Button NextButton
        { 
            get
            { 
                return this._nextButton; 
            }
        } 

        internal Button PreviousButton
        {
            get 
            {
                return this._previousButton; 
            } 
        }
 
        private DateTime DisplayDate
        {
            get
            { 
                return (Owner != null) ? Owner.DisplayDate : DateTime.Today;
            } 
        } 

        #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()
        { 
            base.OnApplyTemplate();

            if (this._previousButton != null)
            { 
                this._previousButton.Click -= new RoutedEventHandler(PreviousButton_Click);
            } 
 
            if (this._nextButton != null)
            { 
                this._nextButton.Click -= new RoutedEventHandler(NextButton_Click);
            }

            if (this._headerButton != null) 
            {
                this._headerButton.Click -= new RoutedEventHandler(HeaderButton_Click); 
            } 

            _monthView = GetTemplateChild(ElementMonthView) as Grid; 
            _yearView = GetTemplateChild(ElementYearView) as Grid;
            _previousButton = GetTemplateChild(ElementPreviousButton) as Button;
            _nextButton = GetTemplateChild(ElementNextButton) as Button;
            _headerButton = GetTemplateChild(ElementHeaderButton) as Button; 
            _disabledVisual = GetTemplateChild(ElementDisabledVisual) as FrameworkElement;
 
            // WPF Compat: Unlike SL, WPF is not able to get elements in template resources with GetTemplateChild() 
            _dayTitleTemplate = null;
            if (Template != null && Template.Resources.Contains(DayTitleTemplateResourceKey)) 
            {
                _dayTitleTemplate = Template.Resources[DayTitleTemplateResourceKey] as DataTemplate;
            }
 
            if (this._previousButton != null)
            { 
                // If the user does not provide a Content value in template, we provide a helper text that can be used in Accessibility 
                // this text is not shown on the UI, just used for Accessibility purposes
                if (this._previousButton.Content == null) 
                {
                    this._previousButton.Content = SR.Get(SRID.Calendar_PreviousButtonName);
                }
 
                this._previousButton.Click += new RoutedEventHandler(PreviousButton_Click);
            } 
 
            if (this._nextButton != null)
            { 
                // If the user does not provide a Content value in template, we provide a helper text that can be used in Accessibility
                // this text is not shown on the UI, just used for Accessibility purposes
                if (this._nextButton.Content == null)
                { 
                    this._nextButton.Content = SR.Get(SRID.Calendar_NextButtonName);
                } 
 
                this._nextButton.Click += new RoutedEventHandler(NextButton_Click);
            } 

            if (this._headerButton != null)
            {
                this._headerButton.Click += new RoutedEventHandler(HeaderButton_Click); 
            }
 
            PopulateGrids(); 

            if (this.Owner != null) 
            {
                switch (this.Owner.DisplayMode)
                {
                    case CalendarMode.Year: 
                        UpdateYearMode();
                        break; 
                    case CalendarMode.Decade: 
                        UpdateDecadeMode();
                        break; 
                    case CalendarMode.Month:
                        UpdateMonthMode();
                        break;
 
                    default:
                        Debug.Assert(false); 
                        break; 
                }
            } 
            else
            {
                UpdateMonthMode();
            } 
        }
 
        #endregion Public Methods 

        #region Protected Methods 

        internal override void ChangeVisualState(bool useTransitions)
        {
            if (!IsEnabled) 
            {
                VisualStateManager.GoToState(this, VisualStates.StateDisabled, useTransitions); 
            } 
            else
            { 
                VisualStateManager.GoToState(this, VisualStates.StateNormal, useTransitions);
            }

            base.ChangeVisualState(useTransitions); 
        }
 
        protected override void OnMouseUp(MouseButtonEventArgs e) 
        {
            base.OnMouseUp(e); 

            if (this.IsMouseCaptured)
            {
                this.ReleaseMouseCapture(); 
            }
 
            this._isMonthPressed = false; 
            this._isDayPressed = false;
 
            // In Month mode, we may need to end a drag selection even if  the mouse up isn't on the calendar.
            if (!e.Handled &&
                this.Owner.DisplayMode == CalendarMode.Month &&
                this.Owner.HoverEnd.HasValue) 
            {
                FinishSelection(this.Owner.HoverEnd.Value); 
            } 
        }
 
        protected override void OnLostMouseCapture(MouseEventArgs e)
        {
            base.OnLostMouseCapture(e);
 
            if (!this.IsMouseCaptured)
            { 
                this._isDayPressed = false; 
                this._isMonthPressed = false;
            } 
        }

        #endregion
 
        #region Internal Methods
 
        internal void UpdateDecadeMode() 
        {
            DateTime selectedYear; 

            if (this.Owner != null)
            {
                selectedYear = this.Owner.DisplayYear; 
            }
            else 
            { 
                selectedYear = DateTime.Today;
            } 

            int decade = GetDecadeForDecadeMode(selectedYear);
            int decadeEnd = decade + 9;
 
            SetDecadeModeHeaderButton(decade);
            SetDecadeModePreviousButton(decade); 
            SetDecadeModeNextButton(decadeEnd); 

            if (_yearView != null) 
            {
                SetYearButtons(decade, decadeEnd);
            }
        } 

        internal void UpdateMonthMode() 
        { 
            SetMonthModeHeaderButton();
            SetMonthModePreviousButton(); 
            SetMonthModeNextButton();

            if (_monthView != null)
            { 
                SetMonthModeDayTitles();
                SetMonthModeCalendarDayButtons(); 
                AddMonthModeHighlight(); 
            }
        } 

        internal void UpdateYearMode()
        {
            SetYearModeHeaderButton(); 
            SetYearModePreviousButton();
            SetYearModeNextButton(); 
 
            if (_yearView != null)
            { 
                SetYearModeMonthButtons();
            }
        }
 
        internal IEnumerable GetCalendarDayButtons()
        { 
            // 
            int count = ROWS * COLS;
            if (MonthView != null) 
            {
                UIElementCollection dayButtonsHost = MonthView.Children;
                for (int childIndex = COLS; childIndex < count; childIndex++)
                { 
                    CalendarDayButton b = dayButtonsHost[childIndex] as CalendarDayButton;
                    if (b != null) 
                    { 
                        yield return b;
                    } 
                }
            }
        }
 
        internal CalendarDayButton GetFocusedCalendarDayButton()
        { 
            foreach (CalendarDayButton b in GetCalendarDayButtons()) 
            {
                if (b != null && b.IsFocused) 
                {
                    return b;
                }
            } 

            return null; 
        } 

        internal CalendarDayButton GetCalendarDayButton(DateTime date) 
        {
            foreach (CalendarDayButton b in GetCalendarDayButtons())
            {
                if (b != null && b.DataContext is DateTime) 
                {
                    if (DateTimeHelper.CompareDays(date, (DateTime)b.DataContext) == 0) 
                    { 
                        return b;
                    } 
                }
            }

            return null; 
        }
 
        internal CalendarButton GetCalendarButton(DateTime date, CalendarMode mode) 
        {
            Debug.Assert(mode != CalendarMode.Month); 

            foreach (CalendarButton b in GetCalendarButtons())
            {
                if (b != null && b.DataContext is DateTime) 
                {
                    if (mode == CalendarMode.Year) 
                    { 
                        if (DateTimeHelper.CompareYearMonth(date, (DateTime)b.DataContext) == 0)
                        { 
                            return b;
                        }
                    }
                    else 
                    {
                        if (date.Year == ((DateTime)b.DataContext).Year) 
                        { 
                            return b;
                        } 
                    }
                }
            }
 
            return null;
        } 
 
        internal CalendarButton GetFocusedCalendarButton()
        { 
            foreach (CalendarButton b in GetCalendarButtons())
            {
                if (b != null && b.IsFocused)
                { 
                    return b;
                } 
            } 

            return null; 
        }

        private IEnumerable GetCalendarButtons()
        { 
            foreach (UIElement element in this.YearView.Children)
            { 
                CalendarButton b = element as CalendarButton; 
                if (b != null)
                { 
                    yield return b;
                }
            }
        } 

        internal void FocusDate(DateTime date) 
        { 
            FrameworkElement focusTarget = null;
 
            switch (this.DisplayMode)
            {
                case CalendarMode.Month:
                { 
                    focusTarget = GetCalendarDayButton(date);
                    break; 
                } 

                case CalendarMode.Year: 
                case CalendarMode.Decade:
                {
                    focusTarget = GetCalendarButton(date, this.DisplayMode);
                    break; 
                }
 
                default: 
                {
                    Debug.Assert(false); 
                    break;
                }
            }
 
            if (focusTarget != null && !focusTarget.IsFocused)
            { 
                focusTarget.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); 
            }
        } 

        #endregion Internal Methods

        #region Private Methods 

        private int GetDecadeForDecadeMode(DateTime selectedYear) 
        { 
            int decade = DateTimeHelper.DecadeOfDate(selectedYear);
 
            // Adjust the decade value if the mouse move selection is on,
            // such that if first or last year among the children are selected
            // then return the current selected decade as is.
            if (_isMonthPressed && _yearView != null) 
            {
                UIElementCollection yearViewChildren = _yearView.Children; 
                int count = yearViewChildren.Count; 

                if (count > 0) 
                {
                    CalendarButton child = yearViewChildren[0] as CalendarButton;
                    if (child != null &&
                        child.DataContext is DateTime && 
                        ((DateTime)child.DataContext).Year == selectedYear.Year)
                    { 
                        return (decade + 10); 
                    }
                } 

                if (count > 1)
                {
                    CalendarButton child = yearViewChildren[count - 1] as CalendarButton; 
                    if (child != null &&
                        child.DataContext is DateTime && 
                        ((DateTime)child.DataContext).Year == selectedYear.Year) 
                    {
                        return (decade - 10); 
                    }
                }
            }
            return decade; 
        }
 
        private void EndDrag(bool ctrl, DateTime selectedDate) 
        {
            if (this.Owner != null) 
            {
                this.Owner.CurrentDate = selectedDate;

                if (this.Owner.HoverStart.HasValue) 
                {
                    if ( 
                        ctrl && 
                        DateTime.Compare(this.Owner.HoverStart.Value, selectedDate) == 0 &&
                        (Owner.SelectionMode == CalendarSelectionMode.SingleDate || Owner.SelectionMode == CalendarSelectionMode.MultipleRange)) 
                    {
                        // Ctrl + single click = toggle
                        this.Owner.SelectedDates.Toggle(selectedDate);
                    } 
                    else
                    { 
                        // this is selection with Mouse, we do not guarantee the range does not include BlackOutDates. 
                        // Use the internal AddRange that omits BlackOutDates based on the SelectionMode
                        this.Owner.SelectedDates.AddRangeInternal(this.Owner.HoverStart.Value, selectedDate); 
                    }

                    Owner.OnDayClick(selectedDate);
                } 
            }
        } 
 
        private void CellOrMonth_PreviewKeyDown(object sender, RoutedEventArgs e)
        { 
            Debug.Assert(e != null);

            if (this.Owner == null)
            { 
                return;
            } 
 
            this.Owner.OnDayOrMonthPreviewKeyDown(e);
        } 

        private void Cell_Clicked(object sender, RoutedEventArgs e)
        {
            if (this.Owner == null) 
            {
                return; 
            } 

            CalendarDayButton b = sender as CalendarDayButton; 
            Debug.Assert(b != null);

            if (!(b.DataContext is DateTime))
            { 
                return;
            } 
 
            // If the day is a blackout day selection is not allowed
            if (!b.IsBlackedOut) 
            {
                DateTime clickedDate = (DateTime)b.DataContext;
                bool ctrl, shift;
 
                CalendarKeyboardHelper.GetMetaKeyState(out ctrl, out shift);
 
                switch (this.Owner.SelectionMode) 
                {
                    case CalendarSelectionMode.None: 
                    {
                        break;
                    }
 
                    case CalendarSelectionMode.SingleDate:
                    { 
                        if (!ctrl) 
                        {
                            this.Owner.SelectedDate = clickedDate; 
                        }
                        else
                        {
                            this.Owner.SelectedDates.Toggle(clickedDate); 
                        }
 
                        break; 
                    }
 
                    case CalendarSelectionMode.SingleRange:
                        {
                            DateTime? lastDate = this.Owner.CurrentDate;
                            this.Owner.SelectedDates.ClearInternal(true /*fireChangeNotification*/); 
                            if (shift && lastDate.HasValue)
                            { 
                                this.Owner.SelectedDates.AddRangeInternal(lastDate.Value, clickedDate); 
                            }
                            else 
                            {
                                this.Owner.SelectedDate = clickedDate;
                                this.Owner.HoverStart = null;
                                this.Owner.HoverEnd = null; 
                            }
 
                            break; 
                        }
 
                    case CalendarSelectionMode.MultipleRange:
                        {
                            if (!ctrl)
                            { 
                                this.Owner.SelectedDates.ClearInternal(true /*fireChangeNotification*/);
                            } 
 
                            if (shift)
                            { 
                                this.Owner.SelectedDates.AddRangeInternal(this.Owner.CurrentDate, clickedDate);
                            }
                            else
                            { 
                                if (!ctrl)
                                { 
                                    this.Owner.SelectedDate = clickedDate; 
                                }
                                else 
                                {
                                    this.Owner.SelectedDates.Toggle(clickedDate);
                                    this.Owner.HoverStart = null;
                                    this.Owner.HoverEnd = null; 
                                }
                            } 
 
                            break;
                        } 
                }

                this.Owner.OnDayClick(clickedDate);
            } 
        }
 
        private void Cell_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
        {
            CalendarDayButton b = sender as CalendarDayButton; 

            if (b == null)
            {
                return; 
            }
 
            if (this.Owner == null || !(b.DataContext is DateTime)) 
            {
                return; 
            }

            if (b.IsBlackedOut)
            { 
                this.Owner.HoverStart = null;
            } 
            else 
            {
                this._isDayPressed = true; 
                Mouse.Capture(this, CaptureMode.SubTree);

                b.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
 
                bool ctrl, shift;
                CalendarKeyboardHelper.GetMetaKeyState(out ctrl, out shift); 
 
                DateTime selectedDate = (DateTime)b.DataContext;
                Debug.Assert(selectedDate != null); 

                switch (this.Owner.SelectionMode)
                {
                    case CalendarSelectionMode.None: 
                    {
                        break; 
                    } 

                    case CalendarSelectionMode.SingleDate: 
                    {
                        this.Owner.DatePickerDisplayDateFlag = true;
                        if (!ctrl)
                        { 
                            this.Owner.SelectedDate = selectedDate;
                        } 
                        else 
                        {
                            this.Owner.SelectedDates.Toggle(selectedDate); 
                        }

                        break;
                    } 

                    case CalendarSelectionMode.SingleRange: 
                    { 
                        this.Owner.SelectedDates.ClearInternal();
 
                        if (shift)
                        {
                            if (!this.Owner.HoverStart.HasValue)
                            { 
                                this.Owner.HoverStart = this.Owner.HoverEnd = this.Owner.CurrentDate;
                            } 
                        } 
                        else
                        { 
                            this.Owner.HoverStart = this.Owner.HoverEnd = selectedDate;
                        }

                        break; 
                    }
 
                    case CalendarSelectionMode.MultipleRange: 
                    {
                        if (!ctrl) 
                        {
                            this.Owner.SelectedDates.ClearInternal();
                        }
 
                        if (shift)
                        { 
                            if (!this.Owner.HoverStart.HasValue) 
                            {
                                this.Owner.HoverStart = this.Owner.HoverEnd = this.Owner.CurrentDate; 
                            }
                        }
                        else
                        { 
                            this.Owner.HoverStart = this.Owner.HoverEnd = selectedDate;
                        } 
 
                        break;
                    } 
                }

                this.Owner.CurrentDate = selectedDate;
                this.Owner.UpdateCellItems(); 
            }
        } 
 
        private void Cell_MouseEnter(object sender, MouseEventArgs e)
        { 
            CalendarDayButton b = sender as CalendarDayButton;
            if (b == null)
            {
                return; 
            }
 
            if (b.IsBlackedOut) 
            {
                return; 
            }

            if (e.LeftButton == MouseButtonState.Pressed && this._isDayPressed)
            { 
                b.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
 
                if (this.Owner == null || !(b.DataContext is DateTime)) 
                {
                    return; 
                }

                DateTime selectedDate = (DateTime)b.DataContext;
 
                switch (this.Owner.SelectionMode)
                { 
                    case CalendarSelectionMode.SingleDate: 
                    {
                        this.Owner.DatePickerDisplayDateFlag = true; 
                        this.Owner.HoverStart = this.Owner.HoverEnd = null;
                        if (this.Owner.SelectedDates.Count == 0)
                        {
                            this.Owner.SelectedDates.Add(selectedDate); 
                        }
                        else 
                        { 
                            this.Owner.SelectedDates[0] = selectedDate;
                        } 

                        return;
                    }
                } 

                this.Owner.HoverEnd = selectedDate; 
                this.Owner.CurrentDate = selectedDate; 
                this.Owner.UpdateCellItems();
            } 
        }


        private void Cell_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
        {
            CalendarDayButton b = sender as CalendarDayButton; 
            if (b == null) 
            {
                return; 
            }

            if (this.Owner == null)
            { 
                return;
            } 
 
            if (!b.IsBlackedOut)
            { 
                this.Owner.OnDayButtonMouseUp(e);
            }

            if (!(b.DataContext is DateTime)) 
            {
                return; 
            } 

            FinishSelection((DateTime)b.DataContext); 
            e.Handled = true;
        }

        private void FinishSelection(DateTime selectedDate) 
        {
            bool ctrl, shift; 
            CalendarKeyboardHelper.GetMetaKeyState(out ctrl, out shift); 

            if (this.Owner.SelectionMode == CalendarSelectionMode.None || this.Owner.SelectionMode == CalendarSelectionMode.SingleDate) 
            {
                this.Owner.OnDayClick(selectedDate);
                return;
            } 

            if (this.Owner.HoverStart.HasValue) 
            { 
                switch (this.Owner.SelectionMode)
                { 
                    case CalendarSelectionMode.SingleRange:
                    {
                        // Update SelectedDates
                        this.Owner.SelectedDates.ClearInternal(); 
                        EndDrag(ctrl, selectedDate);
                        break; 
                    } 

                    case CalendarSelectionMode.MultipleRange: 
                    {
                        // add the selection (either single day or SingleRange day)
                        EndDrag(ctrl, selectedDate);
                        break; 
                    }
                } 
            } 
            else
            { 
                // If the day is blacked out but also a trailing day we should be able to switch months
                CalendarDayButton b = GetCalendarDayButton(selectedDate);
                if (b != null && b.IsInactive && b.IsBlackedOut)
                { 
                    this.Owner.OnDayClick(selectedDate);
                } 
            } 
        }
 
        private void Month_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            CalendarButton b = sender as CalendarButton;
            if (b != null) 
            {
                this._isMonthPressed = true; 
                Mouse.Capture(this, CaptureMode.SubTree); 

                if (this.Owner != null) 
                {
                    this.Owner.OnCalendarButtonPressed(b, false);
                }
            } 
        }
 
        private void Month_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
        {
            CalendarButton b = sender as CalendarButton; 
            if (b != null && this.Owner != null)
            {
                this.Owner.OnCalendarButtonPressed(b, true);
            } 
        }
 
        private void Month_MouseEnter(object sender, MouseEventArgs e) 
        {
            CalendarButton b = sender as CalendarButton; 
            if (b != null)
            {
                if (this._isMonthPressed && this.Owner != null)
                { 
                    this.Owner.OnCalendarButtonPressed(b, false);
                } 
            } 
        }
 
        private void Month_Clicked(object sender, RoutedEventArgs e)
        {
            CalendarButton b = sender as CalendarButton;
            if (b != null) 
            {
                this.Owner.OnCalendarButtonPressed(b, true); 
            } 
        }
 
        private void HeaderButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.Owner != null)
            { 
                if (this.Owner.DisplayMode == CalendarMode.Month)
                { 
                    this.Owner.SetCurrentValueInternal(Calendar.DisplayModeProperty, CalendarMode.Year); 
                }
                else 
                {
                    Debug.Assert(this.Owner.DisplayMode == CalendarMode.Year);

                    this.Owner.SetCurrentValueInternal(Calendar.DisplayModeProperty, CalendarMode.Decade); 
                }
 
                this.FocusDate(this.DisplayDate); 
            }
        } 

        private void PreviousButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.Owner != null) 
            {
                this.Owner.OnPreviousClick(); 
            } 
        }
 
        private void NextButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.Owner != null)
            { 
                this.Owner.OnNextClick();
            } 
        } 

        private void PopulateGrids() 
        {
            if (_monthView != null)
            {
                for (int i = 0; i < COLS; i++) 
                {
                    FrameworkElement titleCell = (this._dayTitleTemplate != null) ? (FrameworkElement)this._dayTitleTemplate.LoadContent() : new ContentControl(); 
                    titleCell.SetValue(Grid.RowProperty, 0); 
                    titleCell.SetValue(Grid.ColumnProperty, i);
                    this._monthView.Children.Add(titleCell); 
                }

                for (int i = 1; i < ROWS; i++)
                { 
                    for (int j = 0; j < COLS; j++)
                    { 
                        CalendarDayButton dayCell = new CalendarDayButton(); 

                        dayCell.Owner = this.Owner; 
                        dayCell.SetValue(Grid.RowProperty, i);
                        dayCell.SetValue(Grid.ColumnProperty, j);
                        dayCell.SetBinding(CalendarDayButton.StyleProperty, GetOwnerBinding("CalendarDayButtonStyle"));
 
                        dayCell.AddHandler(CalendarDayButton.MouseLeftButtonDownEvent, new MouseButtonEventHandler(Cell_MouseLeftButtonDown), true);
                        dayCell.AddHandler(CalendarDayButton.MouseLeftButtonUpEvent, new MouseButtonEventHandler(Cell_MouseLeftButtonUp), true); 
                        dayCell.AddHandler(CalendarDayButton.MouseEnterEvent, new MouseEventHandler(Cell_MouseEnter), true); 
                        dayCell.Click += new RoutedEventHandler(Cell_Clicked);
                        dayCell.AddHandler(PreviewKeyDownEvent, new RoutedEventHandler(CellOrMonth_PreviewKeyDown), true); 

                        this._monthView.Children.Add(dayCell);
                    }
                } 
            }
 
            if (_yearView != null) 
            {
                CalendarButton monthCell; 
                int count = 0;
                for (int i = 0; i < YEAR_ROWS; i++)
                {
                    for (int j = 0; j < YEAR_COLS; j++) 
                    {
                        monthCell = new CalendarButton(); 
 
                        monthCell.Owner = this.Owner;
                        monthCell.SetValue(Grid.RowProperty, i); 
                        monthCell.SetValue(Grid.ColumnProperty, j);
                        monthCell.SetBinding(CalendarButton.StyleProperty, GetOwnerBinding("CalendarButtonStyle"));

                        monthCell.AddHandler(CalendarButton.MouseLeftButtonDownEvent, new MouseButtonEventHandler(Month_MouseLeftButtonDown), true); 
                        monthCell.AddHandler(CalendarButton.MouseLeftButtonUpEvent, new MouseButtonEventHandler(Month_MouseLeftButtonUp), true);
                        monthCell.AddHandler(CalendarButton.MouseEnterEvent, new MouseEventHandler(Month_MouseEnter), true); 
                        monthCell.AddHandler(UIElement.PreviewKeyDownEvent, new RoutedEventHandler(CellOrMonth_PreviewKeyDown), true); 
                        monthCell.Click += new RoutedEventHandler(Month_Clicked);
 
                        this._yearView.Children.Add(monthCell);
                        count++;
                    }
                } 
            }
        } 
 
        #region Month Mode Display
 
        private void SetMonthModeDayTitles()
        {
            if (_monthView != null)
            { 

                string[] shortestDayNames = DateTimeHelper.GetDateFormat(DateTimeHelper.GetCulture(this)).ShortestDayNames; 
 
                for (int childIndex = 0; childIndex < COLS; childIndex++)
                { 
                    FrameworkElement daytitle = _monthView.Children[childIndex] as FrameworkElement;

                    if (daytitle != null && shortestDayNames != null && shortestDayNames.Length > 0)
                    { 
                        if (this.Owner != null)
                        { 
                            daytitle.DataContext = shortestDayNames[(childIndex + (int)this.Owner.FirstDayOfWeek) % shortestDayNames.Length]; 
                        }
                        else 
                        {
                            daytitle.DataContext = shortestDayNames[(childIndex + (int)DateTimeHelper.GetDateFormat( DateTimeHelper.GetCulture(this)).FirstDayOfWeek) % shortestDayNames.Length];
                        }
                    } 
                }
            } 
        } 

        private void SetMonthModeCalendarDayButtons() 
        {
            DateTime firstDayOfMonth = DateTimeHelper.DiscardDayTime(DisplayDate);
            int lastMonthToDisplay = GetNumberOfDisplayedDaysFromPreviousMonth(firstDayOfMonth);
 
            bool isMinMonth = DateTimeHelper.CompareYearMonth(firstDayOfMonth, DateTime.MinValue) <= 0;
            bool isMaxMonth = DateTimeHelper.CompareYearMonth(firstDayOfMonth, DateTime.MaxValue) >= 0; 
            int daysInMonth = _calendar.GetDaysInMonth(firstDayOfMonth.Year, firstDayOfMonth.Month); 
            CultureInfo culture = DateTimeHelper.GetCulture(this);
 
            int count = ROWS * COLS;
            for (int childIndex = COLS; childIndex < count; childIndex++)
            {
                CalendarDayButton childButton = _monthView.Children[childIndex] as CalendarDayButton; 

                Debug.Assert(childButton != null); 
 
                int dayOffset = childIndex - lastMonthToDisplay - COLS;
                if ((!isMinMonth || (dayOffset >= 0)) && (!isMaxMonth || (dayOffset < daysInMonth))) 
                {
                    DateTime dateToAdd = _calendar.AddDays(firstDayOfMonth, dayOffset);
                    SetMonthModeDayButtonState(childButton, dateToAdd);
                    childButton.DataContext = dateToAdd; 
                    childButton.SetContentInternal(DateTimeHelper.ToDayString(dateToAdd, culture));
                } 
                else 
                {
                    SetMonthModeDayButtonState(childButton, null); 
                    childButton.DataContext = null;
                    childButton.SetContentInternal(DateTimeHelper.ToDayString(null, culture));
                }
            } 
        }
 
        private void SetMonthModeDayButtonState(CalendarDayButton childButton, DateTime? dateToAdd) 
        {
            if (this.Owner != null) 
            {
                if (dateToAdd.HasValue)
                {
                    childButton.Visibility = Visibility.Visible; 

                    // If the day is outside the DisplayDateStart/End boundary, do not show it 
                    if (DateTimeHelper.CompareDays(dateToAdd.Value, this.Owner.DisplayDateStartInternal) < 0 || DateTimeHelper.CompareDays(dateToAdd.Value, this.Owner.DisplayDateEndInternal) > 0) 
                    {
                        childButton.IsEnabled = false; 
                        childButton.Visibility = Visibility.Hidden;
                    }
                    else
                    { 
                        childButton.IsEnabled = true;
 
                        // SET IF THE DAY IS SELECTABLE OR NOT 
                        childButton.SetValue(
                            CalendarDayButton.IsBlackedOutPropertyKey, 
                            this.Owner.BlackoutDates.Contains(dateToAdd.Value));

                        // SET IF THE DAY IS ACTIVE OR NOT: set if the day is a trailing day or not
                        childButton.SetValue( 
                            CalendarDayButton.IsInactivePropertyKey,
                            DateTimeHelper.CompareYearMonth(dateToAdd.Value, this.Owner.DisplayDateInternal) != 0); 
 
                        // SET IF THE DAY IS TODAY OR NOT
                        if (DateTimeHelper.CompareDays(dateToAdd.Value, DateTime.Today) == 0) 
                        {
                            childButton.SetValue(CalendarDayButton.IsTodayPropertyKey, true);
                        }
                        else 
                        {
                            childButton.SetValue(CalendarDayButton.IsTodayPropertyKey, false); 
                        } 

                        // the child button doesn't get change notificaitons from Calendar.IsTodayHighlighted 
                        // so we need up change visual states to ensure the IsToday is up to date.
                        childButton.NotifyNeedsVisualStateUpdate();

                        // SET IF THE DAY IS SELECTED OR NOT 
                        // Since we should be comparing the Date values not DateTime values, we can't use this.Owner.SelectedDates.Contains(dateToAdd) directly
                        bool isSelected = false; 
                        foreach (DateTime item in this.Owner.SelectedDates) 
                        {
                            isSelected |= (DateTimeHelper.CompareDays(dateToAdd.Value, item) == 0); 
                        }

                        childButton.SetValue(CalendarDayButton.IsSelectedPropertyKey, isSelected);
                    } 
                }
                else 
                { 
                    childButton.Visibility = Visibility.Hidden;
                    childButton.IsEnabled = false; 
                    childButton.SetValue(CalendarDayButton.IsBlackedOutPropertyKey, false);
                    childButton.SetValue(CalendarDayButton.IsInactivePropertyKey, true);
                    childButton.SetValue(CalendarDayButton.IsTodayPropertyKey, false);
                    childButton.SetValue(CalendarDayButton.IsSelectedPropertyKey, false); 
                }
            } 
        } 

        private void AddMonthModeHighlight() 
        {
            var owner = this.Owner;
            if (owner == null)
            { 
                return;
            } 
 
            if (owner.HoverStart.HasValue && owner.HoverEnd.HasValue)
            { 
                DateTime hStart = owner.HoverEnd.Value;
                DateTime hEnd = owner.HoverEnd.Value;

                int daysToHighlight = DateTimeHelper.CompareDays(owner.HoverEnd.Value, owner.HoverStart.Value); 
                if (daysToHighlight < 0)
                { 
                    hEnd = owner.HoverStart.Value; 
                }
                else 
                {
                    hStart = owner.HoverStart.Value;
                }
 
                int count = ROWS * COLS;
 
                for (int childIndex = COLS; childIndex < count; childIndex++) 
                {
                    CalendarDayButton childButton = _monthView.Children[childIndex] as CalendarDayButton; 
                    if (childButton.DataContext is DateTime)
                    {
                        DateTime date = (DateTime)childButton.DataContext;
                        childButton.SetValue( 
                            CalendarDayButton.IsHighlightedPropertyKey,
                            (daysToHighlight != 0) && DateTimeHelper.InRange(date, hStart, hEnd)); 
                    } 
                    else
                    { 
                        childButton.SetValue(CalendarDayButton.IsHighlightedPropertyKey, false);
                    }
                }
            } 
            else
            { 
                int count = ROWS * COLS; 

                for (int childIndex = COLS; childIndex < count; childIndex++) 
                {
                    CalendarDayButton childButton = _monthView.Children[childIndex] as CalendarDayButton;
                    childButton.SetValue(CalendarDayButton.IsHighlightedPropertyKey, false);
                } 
            }
        } 
 
        private void SetMonthModeHeaderButton()
        { 
            if (this._headerButton != null)
            {
                this._headerButton.Content = DateTimeHelper.ToYearMonthPatternString(DisplayDate, DateTimeHelper.GetCulture(this));
 
                if (this.Owner != null)
                { 
                    this._headerButton.IsEnabled = true; 
                }
            } 
        }

        private void SetMonthModeNextButton()
        { 
            if (this.Owner != null && _nextButton != null)
            { 
                DateTime firstDayOfMonth = DateTimeHelper.DiscardDayTime(DisplayDate); 

                // DisplayDate is equal to DateTime.MaxValue 
                if (DateTimeHelper.CompareYearMonth(firstDayOfMonth, DateTime.MaxValue) == 0)
                {
                    _nextButton.IsEnabled = false;
                } 
                else
                { 
                    // Since we are sure DisplayDate is not equal to DateTime.MaxValue, 
                    // it is safe to use AddMonths
                    DateTime firstDayOfNextMonth = _calendar.AddMonths(firstDayOfMonth, 1); 
                    _nextButton.IsEnabled = (DateTimeHelper.CompareDays(this.Owner.DisplayDateEndInternal, firstDayOfNextMonth) > -1);
                }
            }
        } 

        private void SetMonthModePreviousButton() 
        { 
            if (this.Owner != null && _previousButton != null)
            { 
                DateTime firstDayOfMonth = DateTimeHelper.DiscardDayTime(DisplayDate);
                _previousButton.IsEnabled = (DateTimeHelper.CompareDays(this.Owner.DisplayDateStartInternal, firstDayOfMonth) < 0);
            }
        } 

        #endregion 
 
        #region Year Mode Display
 
        private void SetYearButtons(int decade, int decadeEnd)
        {
            int year;
            int count = -1; 
            foreach (object child in _yearView.Children)
            { 
                CalendarButton childButton = child as CalendarButton; 
                Debug.Assert(childButton != null);
                year = decade + count; 

                if (year <= DateTime.MaxValue.Year && year >= DateTime.MinValue.Year)
                {
                    // There should be no time component. Time is 12:00 AM 
                    DateTime day = new DateTime(year, 1, 1);
                    childButton.DataContext = day; 
                    childButton.SetContentInternal(DateTimeHelper.ToYearString(day, DateTimeHelper.GetCulture(this))); 
                    childButton.Visibility = Visibility.Visible;
 
                    if (this.Owner != null)
                    {
                        childButton.HasSelectedDays = (Owner.DisplayDate.Year == year);
 
                        if (year < this.Owner.DisplayDateStartInternal.Year || year > this.Owner.DisplayDateEndInternal.Year)
                        { 
                            childButton.IsEnabled = false; 
                            childButton.Opacity = 0;
                        } 
                        else
                        {
                            childButton.IsEnabled = true;
                            childButton.Opacity = 1; 
                        }
                    } 
 
                    // SET IF THE YEAR IS INACTIVE OR NOT: set if the year is a trailing year or not
                    childButton.IsInactive = year < decade || year > decadeEnd; 
                }
                else
                {
                    childButton.DataContext = null; 
                    childButton.IsEnabled = false;
                    childButton.Opacity = 0; 
                } 

                count++; 
            }
        }

        private void SetYearModeMonthButtons() 
        {
            int count = 0; 
            foreach (object child in _yearView.Children) 
            {
                CalendarButton childButton = child as CalendarButton; 
                Debug.Assert(childButton != null);

                // There should be no time component. Time is 12:00 AM
                DateTime day = new DateTime(DisplayDate.Year, count + 1, 1); 
                childButton.DataContext = day;
                childButton.SetContentInternal(DateTimeHelper.ToAbbreviatedMonthString(day, DateTimeHelper.GetCulture(this))); 
                childButton.Visibility = Visibility.Visible; 

                if (this.Owner != null) 
                {
                    Debug.Assert(this.Owner.DisplayDateInternal != null);
                    childButton.HasSelectedDays = (DateTimeHelper.CompareYearMonth(day, this.Owner.DisplayDateInternal) == 0);
 
                    if (DateTimeHelper.CompareYearMonth(day, this.Owner.DisplayDateStartInternal) < 0 || DateTimeHelper.CompareYearMonth(day, this.Owner.DisplayDateEndInternal) > 0)
                    { 
                        childButton.IsEnabled = false; 
                        childButton.Opacity = 0;
                    } 
                    else
                    {
                        childButton.IsEnabled = true;
                        childButton.Opacity = 1; 
                    }
                } 
 
                childButton.IsInactive = false;
                count++; 
            }
        }

        private void SetYearModeHeaderButton() 
        {
            if (this._headerButton != null) 
            { 
                this._headerButton.IsEnabled = true;
                this._headerButton.Content = DateTimeHelper.ToYearString(DisplayDate, DateTimeHelper.GetCulture(this)); 
            }
        }

        private void SetYearModeNextButton() 
        {
            if (this.Owner != null && _nextButton != null) 
            { 
                _nextButton.IsEnabled = (this.Owner.DisplayDateEndInternal.Year != DisplayDate.Year);
            } 
        }

        private void SetYearModePreviousButton()
        { 
            if (this.Owner != null && _previousButton != null)
            { 
                _previousButton.IsEnabled = (this.Owner.DisplayDateStartInternal.Year != DisplayDate.Year); 
            }
        } 

        #endregion Year Mode Display

        #region Decade Mode Display 

        private void SetDecadeModeHeaderButton(int decade) 
        { 
            if (this._headerButton != null)
            { 
                this._headerButton.Content = DateTimeHelper.ToDecadeRangeString(decade, this);
                this._headerButton.IsEnabled = false;
            }
        } 

        private void SetDecadeModeNextButton(int decadeEnd) 
        { 
            if (this.Owner != null && _nextButton != null)
            { 
                _nextButton.IsEnabled = (this.Owner.DisplayDateEndInternal.Year > decadeEnd);
            }
        }
 
        private void SetDecadeModePreviousButton(int decade)
        { 
            if (this.Owner != null && _previousButton != null) 
            {
                _previousButton.IsEnabled = (decade > this.Owner.DisplayDateStartInternal.Year); 
            }
        }

        #endregion Decade Mode Display 

        // How many days of the previous month need to be displayed 
        private int GetNumberOfDisplayedDaysFromPreviousMonth(DateTime firstOfMonth) 
        {
            DayOfWeek day = _calendar.GetDayOfWeek(firstOfMonth); 
            int i;

            if (this.Owner != null)
            { 
                i = ((day - this.Owner.FirstDayOfWeek + NUMBER_OF_DAYS_IN_WEEK) % NUMBER_OF_DAYS_IN_WEEK);
            } 
            else 
            {
                i = ((day - DateTimeHelper.GetDateFormat(DateTimeHelper.GetCulture(this)).FirstDayOfWeek + NUMBER_OF_DAYS_IN_WEEK) % NUMBER_OF_DAYS_IN_WEEK); 
            }

            if (i == 0)
            { 
                return NUMBER_OF_DAYS_IN_WEEK;
            } 
            else 
            {
                return i; 
            }
        }

        ///  
        /// Gets a binding to a property on the owning calendar
        ///  
        ///  
        /// 
        private BindingBase GetOwnerBinding(string propertyName) 
        {
            Binding result = new Binding(propertyName);
            result.Source = this.Owner;
            return result; 
        }
 
        #endregion Private Methods 

        #region Resource Keys 

        /// 
        ///     Resource key for DayTitleTemplate
        ///  
        public static ComponentResourceKey DayTitleTemplateResourceKey
        { 
            get 
            {
                if (_dayTitleTemplateResourceKey == null) 
                {
                    _dayTitleTemplateResourceKey = new ComponentResourceKey(typeof(CalendarItem), ElementDayTitleTemplate);
                }
 
                return _dayTitleTemplateResourceKey;
            } 
        } 

        #endregion 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
//--------------------------------------------------------------------------- 

using System; 
using System.Collections.Generic; 
using System.Diagnostics;
using System.Globalization; 
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input; 

namespace System.Windows.Controls.Primitives 
{ 
    [TemplatePart(Name = CalendarItem.ElementRoot, Type = typeof(FrameworkElement))]
    [TemplatePart(Name = CalendarItem.ElementHeaderButton, Type = typeof(Button))] 
    [TemplatePart(Name = CalendarItem.ElementPreviousButton, Type = typeof(Button))]
    [TemplatePart(Name = CalendarItem.ElementNextButton, Type = typeof(Button))]
    [TemplatePart(Name = CalendarItem.ElementDayTitleTemplate, Type = typeof(DataTemplate))]
    [TemplatePart(Name = CalendarItem.ElementMonthView, Type = typeof(Grid))] 
    [TemplatePart(Name = CalendarItem.ElementYearView, Type = typeof(Grid))]
    [TemplatePart(Name = CalendarItem.ElementDisabledVisual, Type = typeof(FrameworkElement))] 
    public sealed partial class CalendarItem : Control 
    {
        #region Constants 
        private const string ElementRoot = "PART_Root";
        private const string ElementHeaderButton = "PART_HeaderButton";
        private const string ElementPreviousButton = "PART_PreviousButton";
        private const string ElementNextButton = "PART_NextButton"; 
        private const string ElementDayTitleTemplate = "DayTitleTemplate";
        private const string ElementMonthView = "PART_MonthView"; 
        private const string ElementYearView = "PART_YearView"; 
        private const string ElementDisabledVisual = "PART_DisabledVisual";
 
        private const int COLS = 7;
        private const int ROWS = 7;
        private const int YEAR_COLS = 4;
        private const int YEAR_ROWS = 3; 
        private const int NUMBER_OF_DAYS_IN_WEEK = 7;
 
        #endregion Constants 

        #region Data 

        private static ComponentResourceKey _dayTitleTemplateResourceKey = null;

        private System.Globalization.Calendar _calendar = new GregorianCalendar(); 
        private DataTemplate _dayTitleTemplate;
        private FrameworkElement _disabledVisual; 
        private Button _headerButton; 
        private Grid _monthView;
        private Button _nextButton; 
        private Button _previousButton;
        private Grid _yearView;
        private bool _isMonthPressed;
        private bool _isDayPressed; 

        #endregion Data 
 
        static CalendarItem()
        { 
            DefaultStyleKeyProperty.OverrideMetadata(typeof(CalendarItem), new FrameworkPropertyMetadata(typeof(CalendarItem)));
            FocusableProperty.OverrideMetadata(typeof(CalendarItem), new FrameworkPropertyMetadata(false));
            KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(CalendarItem), new FrameworkPropertyMetadata(KeyboardNavigationMode.Once));
            KeyboardNavigation.DirectionalNavigationProperty.OverrideMetadata(typeof(CalendarItem), new FrameworkPropertyMetadata(KeyboardNavigationMode.Contained)); 

            IsEnabledProperty.OverrideMetadata(typeof(CalendarItem), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); 
        } 

        ///  
        /// Represents the month that is used in Calendar Control.
        /// 
        public CalendarItem()
        { 
        }
 
        #region Internal Properties 

        internal Grid MonthView 
        {
            get { return _monthView; }
        }
 
        internal Calendar Owner
        { 
            get; 
            set;
        } 

        internal Grid YearView
        {
            get { return _yearView; } 
        }
 
        #endregion Internal Properties 

        #region Private Properties 

        /// 
        /// Gets a value indicating whether the calendar is displayed in months, years or decades.
        ///  
        private CalendarMode DisplayMode
        { 
            get 
            {
                return (this.Owner != null) ? this.Owner.DisplayMode : CalendarMode.Month; 
            }
        }

        internal Button HeaderButton 
        {
            get 
            { 
                return this._headerButton;
            } 
        }

        internal Button NextButton
        { 
            get
            { 
                return this._nextButton; 
            }
        } 

        internal Button PreviousButton
        {
            get 
            {
                return this._previousButton; 
            } 
        }
 
        private DateTime DisplayDate
        {
            get
            { 
                return (Owner != null) ? Owner.DisplayDate : DateTime.Today;
            } 
        } 

        #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()
        { 
            base.OnApplyTemplate();

            if (this._previousButton != null)
            { 
                this._previousButton.Click -= new RoutedEventHandler(PreviousButton_Click);
            } 
 
            if (this._nextButton != null)
            { 
                this._nextButton.Click -= new RoutedEventHandler(NextButton_Click);
            }

            if (this._headerButton != null) 
            {
                this._headerButton.Click -= new RoutedEventHandler(HeaderButton_Click); 
            } 

            _monthView = GetTemplateChild(ElementMonthView) as Grid; 
            _yearView = GetTemplateChild(ElementYearView) as Grid;
            _previousButton = GetTemplateChild(ElementPreviousButton) as Button;
            _nextButton = GetTemplateChild(ElementNextButton) as Button;
            _headerButton = GetTemplateChild(ElementHeaderButton) as Button; 
            _disabledVisual = GetTemplateChild(ElementDisabledVisual) as FrameworkElement;
 
            // WPF Compat: Unlike SL, WPF is not able to get elements in template resources with GetTemplateChild() 
            _dayTitleTemplate = null;
            if (Template != null && Template.Resources.Contains(DayTitleTemplateResourceKey)) 
            {
                _dayTitleTemplate = Template.Resources[DayTitleTemplateResourceKey] as DataTemplate;
            }
 
            if (this._previousButton != null)
            { 
                // If the user does not provide a Content value in template, we provide a helper text that can be used in Accessibility 
                // this text is not shown on the UI, just used for Accessibility purposes
                if (this._previousButton.Content == null) 
                {
                    this._previousButton.Content = SR.Get(SRID.Calendar_PreviousButtonName);
                }
 
                this._previousButton.Click += new RoutedEventHandler(PreviousButton_Click);
            } 
 
            if (this._nextButton != null)
            { 
                // If the user does not provide a Content value in template, we provide a helper text that can be used in Accessibility
                // this text is not shown on the UI, just used for Accessibility purposes
                if (this._nextButton.Content == null)
                { 
                    this._nextButton.Content = SR.Get(SRID.Calendar_NextButtonName);
                } 
 
                this._nextButton.Click += new RoutedEventHandler(NextButton_Click);
            } 

            if (this._headerButton != null)
            {
                this._headerButton.Click += new RoutedEventHandler(HeaderButton_Click); 
            }
 
            PopulateGrids(); 

            if (this.Owner != null) 
            {
                switch (this.Owner.DisplayMode)
                {
                    case CalendarMode.Year: 
                        UpdateYearMode();
                        break; 
                    case CalendarMode.Decade: 
                        UpdateDecadeMode();
                        break; 
                    case CalendarMode.Month:
                        UpdateMonthMode();
                        break;
 
                    default:
                        Debug.Assert(false); 
                        break; 
                }
            } 
            else
            {
                UpdateMonthMode();
            } 
        }
 
        #endregion Public Methods 

        #region Protected Methods 

        internal override void ChangeVisualState(bool useTransitions)
        {
            if (!IsEnabled) 
            {
                VisualStateManager.GoToState(this, VisualStates.StateDisabled, useTransitions); 
            } 
            else
            { 
                VisualStateManager.GoToState(this, VisualStates.StateNormal, useTransitions);
            }

            base.ChangeVisualState(useTransitions); 
        }
 
        protected override void OnMouseUp(MouseButtonEventArgs e) 
        {
            base.OnMouseUp(e); 

            if (this.IsMouseCaptured)
            {
                this.ReleaseMouseCapture(); 
            }
 
            this._isMonthPressed = false; 
            this._isDayPressed = false;
 
            // In Month mode, we may need to end a drag selection even if  the mouse up isn't on the calendar.
            if (!e.Handled &&
                this.Owner.DisplayMode == CalendarMode.Month &&
                this.Owner.HoverEnd.HasValue) 
            {
                FinishSelection(this.Owner.HoverEnd.Value); 
            } 
        }
 
        protected override void OnLostMouseCapture(MouseEventArgs e)
        {
            base.OnLostMouseCapture(e);
 
            if (!this.IsMouseCaptured)
            { 
                this._isDayPressed = false; 
                this._isMonthPressed = false;
            } 
        }

        #endregion
 
        #region Internal Methods
 
        internal void UpdateDecadeMode() 
        {
            DateTime selectedYear; 

            if (this.Owner != null)
            {
                selectedYear = this.Owner.DisplayYear; 
            }
            else 
            { 
                selectedYear = DateTime.Today;
            } 

            int decade = GetDecadeForDecadeMode(selectedYear);
            int decadeEnd = decade + 9;
 
            SetDecadeModeHeaderButton(decade);
            SetDecadeModePreviousButton(decade); 
            SetDecadeModeNextButton(decadeEnd); 

            if (_yearView != null) 
            {
                SetYearButtons(decade, decadeEnd);
            }
        } 

        internal void UpdateMonthMode() 
        { 
            SetMonthModeHeaderButton();
            SetMonthModePreviousButton(); 
            SetMonthModeNextButton();

            if (_monthView != null)
            { 
                SetMonthModeDayTitles();
                SetMonthModeCalendarDayButtons(); 
                AddMonthModeHighlight(); 
            }
        } 

        internal void UpdateYearMode()
        {
            SetYearModeHeaderButton(); 
            SetYearModePreviousButton();
            SetYearModeNextButton(); 
 
            if (_yearView != null)
            { 
                SetYearModeMonthButtons();
            }
        }
 
        internal IEnumerable GetCalendarDayButtons()
        { 
            // 
            int count = ROWS * COLS;
            if (MonthView != null) 
            {
                UIElementCollection dayButtonsHost = MonthView.Children;
                for (int childIndex = COLS; childIndex < count; childIndex++)
                { 
                    CalendarDayButton b = dayButtonsHost[childIndex] as CalendarDayButton;
                    if (b != null) 
                    { 
                        yield return b;
                    } 
                }
            }
        }
 
        internal CalendarDayButton GetFocusedCalendarDayButton()
        { 
            foreach (CalendarDayButton b in GetCalendarDayButtons()) 
            {
                if (b != null && b.IsFocused) 
                {
                    return b;
                }
            } 

            return null; 
        } 

        internal CalendarDayButton GetCalendarDayButton(DateTime date) 
        {
            foreach (CalendarDayButton b in GetCalendarDayButtons())
            {
                if (b != null && b.DataContext is DateTime) 
                {
                    if (DateTimeHelper.CompareDays(date, (DateTime)b.DataContext) == 0) 
                    { 
                        return b;
                    } 
                }
            }

            return null; 
        }
 
        internal CalendarButton GetCalendarButton(DateTime date, CalendarMode mode) 
        {
            Debug.Assert(mode != CalendarMode.Month); 

            foreach (CalendarButton b in GetCalendarButtons())
            {
                if (b != null && b.DataContext is DateTime) 
                {
                    if (mode == CalendarMode.Year) 
                    { 
                        if (DateTimeHelper.CompareYearMonth(date, (DateTime)b.DataContext) == 0)
                        { 
                            return b;
                        }
                    }
                    else 
                    {
                        if (date.Year == ((DateTime)b.DataContext).Year) 
                        { 
                            return b;
                        } 
                    }
                }
            }
 
            return null;
        } 
 
        internal CalendarButton GetFocusedCalendarButton()
        { 
            foreach (CalendarButton b in GetCalendarButtons())
            {
                if (b != null && b.IsFocused)
                { 
                    return b;
                } 
            } 

            return null; 
        }

        private IEnumerable GetCalendarButtons()
        { 
            foreach (UIElement element in this.YearView.Children)
            { 
                CalendarButton b = element as CalendarButton; 
                if (b != null)
                { 
                    yield return b;
                }
            }
        } 

        internal void FocusDate(DateTime date) 
        { 
            FrameworkElement focusTarget = null;
 
            switch (this.DisplayMode)
            {
                case CalendarMode.Month:
                { 
                    focusTarget = GetCalendarDayButton(date);
                    break; 
                } 

                case CalendarMode.Year: 
                case CalendarMode.Decade:
                {
                    focusTarget = GetCalendarButton(date, this.DisplayMode);
                    break; 
                }
 
                default: 
                {
                    Debug.Assert(false); 
                    break;
                }
            }
 
            if (focusTarget != null && !focusTarget.IsFocused)
            { 
                focusTarget.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); 
            }
        } 

        #endregion Internal Methods

        #region Private Methods 

        private int GetDecadeForDecadeMode(DateTime selectedYear) 
        { 
            int decade = DateTimeHelper.DecadeOfDate(selectedYear);
 
            // Adjust the decade value if the mouse move selection is on,
            // such that if first or last year among the children are selected
            // then return the current selected decade as is.
            if (_isMonthPressed && _yearView != null) 
            {
                UIElementCollection yearViewChildren = _yearView.Children; 
                int count = yearViewChildren.Count; 

                if (count > 0) 
                {
                    CalendarButton child = yearViewChildren[0] as CalendarButton;
                    if (child != null &&
                        child.DataContext is DateTime && 
                        ((DateTime)child.DataContext).Year == selectedYear.Year)
                    { 
                        return (decade + 10); 
                    }
                } 

                if (count > 1)
                {
                    CalendarButton child = yearViewChildren[count - 1] as CalendarButton; 
                    if (child != null &&
                        child.DataContext is DateTime && 
                        ((DateTime)child.DataContext).Year == selectedYear.Year) 
                    {
                        return (decade - 10); 
                    }
                }
            }
            return decade; 
        }
 
        private void EndDrag(bool ctrl, DateTime selectedDate) 
        {
            if (this.Owner != null) 
            {
                this.Owner.CurrentDate = selectedDate;

                if (this.Owner.HoverStart.HasValue) 
                {
                    if ( 
                        ctrl && 
                        DateTime.Compare(this.Owner.HoverStart.Value, selectedDate) == 0 &&
                        (Owner.SelectionMode == CalendarSelectionMode.SingleDate || Owner.SelectionMode == CalendarSelectionMode.MultipleRange)) 
                    {
                        // Ctrl + single click = toggle
                        this.Owner.SelectedDates.Toggle(selectedDate);
                    } 
                    else
                    { 
                        // this is selection with Mouse, we do not guarantee the range does not include BlackOutDates. 
                        // Use the internal AddRange that omits BlackOutDates based on the SelectionMode
                        this.Owner.SelectedDates.AddRangeInternal(this.Owner.HoverStart.Value, selectedDate); 
                    }

                    Owner.OnDayClick(selectedDate);
                } 
            }
        } 
 
        private void CellOrMonth_PreviewKeyDown(object sender, RoutedEventArgs e)
        { 
            Debug.Assert(e != null);

            if (this.Owner == null)
            { 
                return;
            } 
 
            this.Owner.OnDayOrMonthPreviewKeyDown(e);
        } 

        private void Cell_Clicked(object sender, RoutedEventArgs e)
        {
            if (this.Owner == null) 
            {
                return; 
            } 

            CalendarDayButton b = sender as CalendarDayButton; 
            Debug.Assert(b != null);

            if (!(b.DataContext is DateTime))
            { 
                return;
            } 
 
            // If the day is a blackout day selection is not allowed
            if (!b.IsBlackedOut) 
            {
                DateTime clickedDate = (DateTime)b.DataContext;
                bool ctrl, shift;
 
                CalendarKeyboardHelper.GetMetaKeyState(out ctrl, out shift);
 
                switch (this.Owner.SelectionMode) 
                {
                    case CalendarSelectionMode.None: 
                    {
                        break;
                    }
 
                    case CalendarSelectionMode.SingleDate:
                    { 
                        if (!ctrl) 
                        {
                            this.Owner.SelectedDate = clickedDate; 
                        }
                        else
                        {
                            this.Owner.SelectedDates.Toggle(clickedDate); 
                        }
 
                        break; 
                    }
 
                    case CalendarSelectionMode.SingleRange:
                        {
                            DateTime? lastDate = this.Owner.CurrentDate;
                            this.Owner.SelectedDates.ClearInternal(true /*fireChangeNotification*/); 
                            if (shift && lastDate.HasValue)
                            { 
                                this.Owner.SelectedDates.AddRangeInternal(lastDate.Value, clickedDate); 
                            }
                            else 
                            {
                                this.Owner.SelectedDate = clickedDate;
                                this.Owner.HoverStart = null;
                                this.Owner.HoverEnd = null; 
                            }
 
                            break; 
                        }
 
                    case CalendarSelectionMode.MultipleRange:
                        {
                            if (!ctrl)
                            { 
                                this.Owner.SelectedDates.ClearInternal(true /*fireChangeNotification*/);
                            } 
 
                            if (shift)
                            { 
                                this.Owner.SelectedDates.AddRangeInternal(this.Owner.CurrentDate, clickedDate);
                            }
                            else
                            { 
                                if (!ctrl)
                                { 
                                    this.Owner.SelectedDate = clickedDate; 
                                }
                                else 
                                {
                                    this.Owner.SelectedDates.Toggle(clickedDate);
                                    this.Owner.HoverStart = null;
                                    this.Owner.HoverEnd = null; 
                                }
                            } 
 
                            break;
                        } 
                }

                this.Owner.OnDayClick(clickedDate);
            } 
        }
 
        private void Cell_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
        {
            CalendarDayButton b = sender as CalendarDayButton; 

            if (b == null)
            {
                return; 
            }
 
            if (this.Owner == null || !(b.DataContext is DateTime)) 
            {
                return; 
            }

            if (b.IsBlackedOut)
            { 
                this.Owner.HoverStart = null;
            } 
            else 
            {
                this._isDayPressed = true; 
                Mouse.Capture(this, CaptureMode.SubTree);

                b.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
 
                bool ctrl, shift;
                CalendarKeyboardHelper.GetMetaKeyState(out ctrl, out shift); 
 
                DateTime selectedDate = (DateTime)b.DataContext;
                Debug.Assert(selectedDate != null); 

                switch (this.Owner.SelectionMode)
                {
                    case CalendarSelectionMode.None: 
                    {
                        break; 
                    } 

                    case CalendarSelectionMode.SingleDate: 
                    {
                        this.Owner.DatePickerDisplayDateFlag = true;
                        if (!ctrl)
                        { 
                            this.Owner.SelectedDate = selectedDate;
                        } 
                        else 
                        {
                            this.Owner.SelectedDates.Toggle(selectedDate); 
                        }

                        break;
                    } 

                    case CalendarSelectionMode.SingleRange: 
                    { 
                        this.Owner.SelectedDates.ClearInternal();
 
                        if (shift)
                        {
                            if (!this.Owner.HoverStart.HasValue)
                            { 
                                this.Owner.HoverStart = this.Owner.HoverEnd = this.Owner.CurrentDate;
                            } 
                        } 
                        else
                        { 
                            this.Owner.HoverStart = this.Owner.HoverEnd = selectedDate;
                        }

                        break; 
                    }
 
                    case CalendarSelectionMode.MultipleRange: 
                    {
                        if (!ctrl) 
                        {
                            this.Owner.SelectedDates.ClearInternal();
                        }
 
                        if (shift)
                        { 
                            if (!this.Owner.HoverStart.HasValue) 
                            {
                                this.Owner.HoverStart = this.Owner.HoverEnd = this.Owner.CurrentDate; 
                            }
                        }
                        else
                        { 
                            this.Owner.HoverStart = this.Owner.HoverEnd = selectedDate;
                        } 
 
                        break;
                    } 
                }

                this.Owner.CurrentDate = selectedDate;
                this.Owner.UpdateCellItems(); 
            }
        } 
 
        private void Cell_MouseEnter(object sender, MouseEventArgs e)
        { 
            CalendarDayButton b = sender as CalendarDayButton;
            if (b == null)
            {
                return; 
            }
 
            if (b.IsBlackedOut) 
            {
                return; 
            }

            if (e.LeftButton == MouseButtonState.Pressed && this._isDayPressed)
            { 
                b.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
 
                if (this.Owner == null || !(b.DataContext is DateTime)) 
                {
                    return; 
                }

                DateTime selectedDate = (DateTime)b.DataContext;
 
                switch (this.Owner.SelectionMode)
                { 
                    case CalendarSelectionMode.SingleDate: 
                    {
                        this.Owner.DatePickerDisplayDateFlag = true; 
                        this.Owner.HoverStart = this.Owner.HoverEnd = null;
                        if (this.Owner.SelectedDates.Count == 0)
                        {
                            this.Owner.SelectedDates.Add(selectedDate); 
                        }
                        else 
                        { 
                            this.Owner.SelectedDates[0] = selectedDate;
                        } 

                        return;
                    }
                } 

                this.Owner.HoverEnd = selectedDate; 
                this.Owner.CurrentDate = selectedDate; 
                this.Owner.UpdateCellItems();
            } 
        }


        private void Cell_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
        {
            CalendarDayButton b = sender as CalendarDayButton; 
            if (b == null) 
            {
                return; 
            }

            if (this.Owner == null)
            { 
                return;
            } 
 
            if (!b.IsBlackedOut)
            { 
                this.Owner.OnDayButtonMouseUp(e);
            }

            if (!(b.DataContext is DateTime)) 
            {
                return; 
            } 

            FinishSelection((DateTime)b.DataContext); 
            e.Handled = true;
        }

        private void FinishSelection(DateTime selectedDate) 
        {
            bool ctrl, shift; 
            CalendarKeyboardHelper.GetMetaKeyState(out ctrl, out shift); 

            if (this.Owner.SelectionMode == CalendarSelectionMode.None || this.Owner.SelectionMode == CalendarSelectionMode.SingleDate) 
            {
                this.Owner.OnDayClick(selectedDate);
                return;
            } 

            if (this.Owner.HoverStart.HasValue) 
            { 
                switch (this.Owner.SelectionMode)
                { 
                    case CalendarSelectionMode.SingleRange:
                    {
                        // Update SelectedDates
                        this.Owner.SelectedDates.ClearInternal(); 
                        EndDrag(ctrl, selectedDate);
                        break; 
                    } 

                    case CalendarSelectionMode.MultipleRange: 
                    {
                        // add the selection (either single day or SingleRange day)
                        EndDrag(ctrl, selectedDate);
                        break; 
                    }
                } 
            } 
            else
            { 
                // If the day is blacked out but also a trailing day we should be able to switch months
                CalendarDayButton b = GetCalendarDayButton(selectedDate);
                if (b != null && b.IsInactive && b.IsBlackedOut)
                { 
                    this.Owner.OnDayClick(selectedDate);
                } 
            } 
        }
 
        private void Month_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            CalendarButton b = sender as CalendarButton;
            if (b != null) 
            {
                this._isMonthPressed = true; 
                Mouse.Capture(this, CaptureMode.SubTree); 

                if (this.Owner != null) 
                {
                    this.Owner.OnCalendarButtonPressed(b, false);
                }
            } 
        }
 
        private void Month_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
        {
            CalendarButton b = sender as CalendarButton; 
            if (b != null && this.Owner != null)
            {
                this.Owner.OnCalendarButtonPressed(b, true);
            } 
        }
 
        private void Month_MouseEnter(object sender, MouseEventArgs e) 
        {
            CalendarButton b = sender as CalendarButton; 
            if (b != null)
            {
                if (this._isMonthPressed && this.Owner != null)
                { 
                    this.Owner.OnCalendarButtonPressed(b, false);
                } 
            } 
        }
 
        private void Month_Clicked(object sender, RoutedEventArgs e)
        {
            CalendarButton b = sender as CalendarButton;
            if (b != null) 
            {
                this.Owner.OnCalendarButtonPressed(b, true); 
            } 
        }
 
        private void HeaderButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.Owner != null)
            { 
                if (this.Owner.DisplayMode == CalendarMode.Month)
                { 
                    this.Owner.SetCurrentValueInternal(Calendar.DisplayModeProperty, CalendarMode.Year); 
                }
                else 
                {
                    Debug.Assert(this.Owner.DisplayMode == CalendarMode.Year);

                    this.Owner.SetCurrentValueInternal(Calendar.DisplayModeProperty, CalendarMode.Decade); 
                }
 
                this.FocusDate(this.DisplayDate); 
            }
        } 

        private void PreviousButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.Owner != null) 
            {
                this.Owner.OnPreviousClick(); 
            } 
        }
 
        private void NextButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.Owner != null)
            { 
                this.Owner.OnNextClick();
            } 
        } 

        private void PopulateGrids() 
        {
            if (_monthView != null)
            {
                for (int i = 0; i < COLS; i++) 
                {
                    FrameworkElement titleCell = (this._dayTitleTemplate != null) ? (FrameworkElement)this._dayTitleTemplate.LoadContent() : new ContentControl(); 
                    titleCell.SetValue(Grid.RowProperty, 0); 
                    titleCell.SetValue(Grid.ColumnProperty, i);
                    this._monthView.Children.Add(titleCell); 
                }

                for (int i = 1; i < ROWS; i++)
                { 
                    for (int j = 0; j < COLS; j++)
                    { 
                        CalendarDayButton dayCell = new CalendarDayButton(); 

                        dayCell.Owner = this.Owner; 
                        dayCell.SetValue(Grid.RowProperty, i);
                        dayCell.SetValue(Grid.ColumnProperty, j);
                        dayCell.SetBinding(CalendarDayButton.StyleProperty, GetOwnerBinding("CalendarDayButtonStyle"));
 
                        dayCell.AddHandler(CalendarDayButton.MouseLeftButtonDownEvent, new MouseButtonEventHandler(Cell_MouseLeftButtonDown), true);
                        dayCell.AddHandler(CalendarDayButton.MouseLeftButtonUpEvent, new MouseButtonEventHandler(Cell_MouseLeftButtonUp), true); 
                        dayCell.AddHandler(CalendarDayButton.MouseEnterEvent, new MouseEventHandler(Cell_MouseEnter), true); 
                        dayCell.Click += new RoutedEventHandler(Cell_Clicked);
                        dayCell.AddHandler(PreviewKeyDownEvent, new RoutedEventHandler(CellOrMonth_PreviewKeyDown), true); 

                        this._monthView.Children.Add(dayCell);
                    }
                } 
            }
 
            if (_yearView != null) 
            {
                CalendarButton monthCell; 
                int count = 0;
                for (int i = 0; i < YEAR_ROWS; i++)
                {
                    for (int j = 0; j < YEAR_COLS; j++) 
                    {
                        monthCell = new CalendarButton(); 
 
                        monthCell.Owner = this.Owner;
                        monthCell.SetValue(Grid.RowProperty, i); 
                        monthCell.SetValue(Grid.ColumnProperty, j);
                        monthCell.SetBinding(CalendarButton.StyleProperty, GetOwnerBinding("CalendarButtonStyle"));

                        monthCell.AddHandler(CalendarButton.MouseLeftButtonDownEvent, new MouseButtonEventHandler(Month_MouseLeftButtonDown), true); 
                        monthCell.AddHandler(CalendarButton.MouseLeftButtonUpEvent, new MouseButtonEventHandler(Month_MouseLeftButtonUp), true);
                        monthCell.AddHandler(CalendarButton.MouseEnterEvent, new MouseEventHandler(Month_MouseEnter), true); 
                        monthCell.AddHandler(UIElement.PreviewKeyDownEvent, new RoutedEventHandler(CellOrMonth_PreviewKeyDown), true); 
                        monthCell.Click += new RoutedEventHandler(Month_Clicked);
 
                        this._yearView.Children.Add(monthCell);
                        count++;
                    }
                } 
            }
        } 
 
        #region Month Mode Display
 
        private void SetMonthModeDayTitles()
        {
            if (_monthView != null)
            { 

                string[] shortestDayNames = DateTimeHelper.GetDateFormat(DateTimeHelper.GetCulture(this)).ShortestDayNames; 
 
                for (int childIndex = 0; childIndex < COLS; childIndex++)
                { 
                    FrameworkElement daytitle = _monthView.Children[childIndex] as FrameworkElement;

                    if (daytitle != null && shortestDayNames != null && shortestDayNames.Length > 0)
                    { 
                        if (this.Owner != null)
                        { 
                            daytitle.DataContext = shortestDayNames[(childIndex + (int)this.Owner.FirstDayOfWeek) % shortestDayNames.Length]; 
                        }
                        else 
                        {
                            daytitle.DataContext = shortestDayNames[(childIndex + (int)DateTimeHelper.GetDateFormat( DateTimeHelper.GetCulture(this)).FirstDayOfWeek) % shortestDayNames.Length];
                        }
                    } 
                }
            } 
        } 

        private void SetMonthModeCalendarDayButtons() 
        {
            DateTime firstDayOfMonth = DateTimeHelper.DiscardDayTime(DisplayDate);
            int lastMonthToDisplay = GetNumberOfDisplayedDaysFromPreviousMonth(firstDayOfMonth);
 
            bool isMinMonth = DateTimeHelper.CompareYearMonth(firstDayOfMonth, DateTime.MinValue) <= 0;
            bool isMaxMonth = DateTimeHelper.CompareYearMonth(firstDayOfMonth, DateTime.MaxValue) >= 0; 
            int daysInMonth = _calendar.GetDaysInMonth(firstDayOfMonth.Year, firstDayOfMonth.Month); 
            CultureInfo culture = DateTimeHelper.GetCulture(this);
 
            int count = ROWS * COLS;
            for (int childIndex = COLS; childIndex < count; childIndex++)
            {
                CalendarDayButton childButton = _monthView.Children[childIndex] as CalendarDayButton; 

                Debug.Assert(childButton != null); 
 
                int dayOffset = childIndex - lastMonthToDisplay - COLS;
                if ((!isMinMonth || (dayOffset >= 0)) && (!isMaxMonth || (dayOffset < daysInMonth))) 
                {
                    DateTime dateToAdd = _calendar.AddDays(firstDayOfMonth, dayOffset);
                    SetMonthModeDayButtonState(childButton, dateToAdd);
                    childButton.DataContext = dateToAdd; 
                    childButton.SetContentInternal(DateTimeHelper.ToDayString(dateToAdd, culture));
                } 
                else 
                {
                    SetMonthModeDayButtonState(childButton, null); 
                    childButton.DataContext = null;
                    childButton.SetContentInternal(DateTimeHelper.ToDayString(null, culture));
                }
            } 
        }
 
        private void SetMonthModeDayButtonState(CalendarDayButton childButton, DateTime? dateToAdd) 
        {
            if (this.Owner != null) 
            {
                if (dateToAdd.HasValue)
                {
                    childButton.Visibility = Visibility.Visible; 

                    // If the day is outside the DisplayDateStart/End boundary, do not show it 
                    if (DateTimeHelper.CompareDays(dateToAdd.Value, this.Owner.DisplayDateStartInternal) < 0 || DateTimeHelper.CompareDays(dateToAdd.Value, this.Owner.DisplayDateEndInternal) > 0) 
                    {
                        childButton.IsEnabled = false; 
                        childButton.Visibility = Visibility.Hidden;
                    }
                    else
                    { 
                        childButton.IsEnabled = true;
 
                        // SET IF THE DAY IS SELECTABLE OR NOT 
                        childButton.SetValue(
                            CalendarDayButton.IsBlackedOutPropertyKey, 
                            this.Owner.BlackoutDates.Contains(dateToAdd.Value));

                        // SET IF THE DAY IS ACTIVE OR NOT: set if the day is a trailing day or not
                        childButton.SetValue( 
                            CalendarDayButton.IsInactivePropertyKey,
                            DateTimeHelper.CompareYearMonth(dateToAdd.Value, this.Owner.DisplayDateInternal) != 0); 
 
                        // SET IF THE DAY IS TODAY OR NOT
                        if (DateTimeHelper.CompareDays(dateToAdd.Value, DateTime.Today) == 0) 
                        {
                            childButton.SetValue(CalendarDayButton.IsTodayPropertyKey, true);
                        }
                        else 
                        {
                            childButton.SetValue(CalendarDayButton.IsTodayPropertyKey, false); 
                        } 

                        // the child button doesn't get change notificaitons from Calendar.IsTodayHighlighted 
                        // so we need up change visual states to ensure the IsToday is up to date.
                        childButton.NotifyNeedsVisualStateUpdate();

                        // SET IF THE DAY IS SELECTED OR NOT 
                        // Since we should be comparing the Date values not DateTime values, we can't use this.Owner.SelectedDates.Contains(dateToAdd) directly
                        bool isSelected = false; 
                        foreach (DateTime item in this.Owner.SelectedDates) 
                        {
                            isSelected |= (DateTimeHelper.CompareDays(dateToAdd.Value, item) == 0); 
                        }

                        childButton.SetValue(CalendarDayButton.IsSelectedPropertyKey, isSelected);
                    } 
                }
                else 
                { 
                    childButton.Visibility = Visibility.Hidden;
                    childButton.IsEnabled = false; 
                    childButton.SetValue(CalendarDayButton.IsBlackedOutPropertyKey, false);
                    childButton.SetValue(CalendarDayButton.IsInactivePropertyKey, true);
                    childButton.SetValue(CalendarDayButton.IsTodayPropertyKey, false);
                    childButton.SetValue(CalendarDayButton.IsSelectedPropertyKey, false); 
                }
            } 
        } 

        private void AddMonthModeHighlight() 
        {
            var owner = this.Owner;
            if (owner == null)
            { 
                return;
            } 
 
            if (owner.HoverStart.HasValue && owner.HoverEnd.HasValue)
            { 
                DateTime hStart = owner.HoverEnd.Value;
                DateTime hEnd = owner.HoverEnd.Value;

                int daysToHighlight = DateTimeHelper.CompareDays(owner.HoverEnd.Value, owner.HoverStart.Value); 
                if (daysToHighlight < 0)
                { 
                    hEnd = owner.HoverStart.Value; 
                }
                else 
                {
                    hStart = owner.HoverStart.Value;
                }
 
                int count = ROWS * COLS;
 
                for (int childIndex = COLS; childIndex < count; childIndex++) 
                {
                    CalendarDayButton childButton = _monthView.Children[childIndex] as CalendarDayButton; 
                    if (childButton.DataContext is DateTime)
                    {
                        DateTime date = (DateTime)childButton.DataContext;
                        childButton.SetValue( 
                            CalendarDayButton.IsHighlightedPropertyKey,
                            (daysToHighlight != 0) && DateTimeHelper.InRange(date, hStart, hEnd)); 
                    } 
                    else
                    { 
                        childButton.SetValue(CalendarDayButton.IsHighlightedPropertyKey, false);
                    }
                }
            } 
            else
            { 
                int count = ROWS * COLS; 

                for (int childIndex = COLS; childIndex < count; childIndex++) 
                {
                    CalendarDayButton childButton = _monthView.Children[childIndex] as CalendarDayButton;
                    childButton.SetValue(CalendarDayButton.IsHighlightedPropertyKey, false);
                } 
            }
        } 
 
        private void SetMonthModeHeaderButton()
        { 
            if (this._headerButton != null)
            {
                this._headerButton.Content = DateTimeHelper.ToYearMonthPatternString(DisplayDate, DateTimeHelper.GetCulture(this));
 
                if (this.Owner != null)
                { 
                    this._headerButton.IsEnabled = true; 
                }
            } 
        }

        private void SetMonthModeNextButton()
        { 
            if (this.Owner != null && _nextButton != null)
            { 
                DateTime firstDayOfMonth = DateTimeHelper.DiscardDayTime(DisplayDate); 

                // DisplayDate is equal to DateTime.MaxValue 
                if (DateTimeHelper.CompareYearMonth(firstDayOfMonth, DateTime.MaxValue) == 0)
                {
                    _nextButton.IsEnabled = false;
                } 
                else
                { 
                    // Since we are sure DisplayDate is not equal to DateTime.MaxValue, 
                    // it is safe to use AddMonths
                    DateTime firstDayOfNextMonth = _calendar.AddMonths(firstDayOfMonth, 1); 
                    _nextButton.IsEnabled = (DateTimeHelper.CompareDays(this.Owner.DisplayDateEndInternal, firstDayOfNextMonth) > -1);
                }
            }
        } 

        private void SetMonthModePreviousButton() 
        { 
            if (this.Owner != null && _previousButton != null)
            { 
                DateTime firstDayOfMonth = DateTimeHelper.DiscardDayTime(DisplayDate);
                _previousButton.IsEnabled = (DateTimeHelper.CompareDays(this.Owner.DisplayDateStartInternal, firstDayOfMonth) < 0);
            }
        } 

        #endregion 
 
        #region Year Mode Display
 
        private void SetYearButtons(int decade, int decadeEnd)
        {
            int year;
            int count = -1; 
            foreach (object child in _yearView.Children)
            { 
                CalendarButton childButton = child as CalendarButton; 
                Debug.Assert(childButton != null);
                year = decade + count; 

                if (year <= DateTime.MaxValue.Year && year >= DateTime.MinValue.Year)
                {
                    // There should be no time component. Time is 12:00 AM 
                    DateTime day = new DateTime(year, 1, 1);
                    childButton.DataContext = day; 
                    childButton.SetContentInternal(DateTimeHelper.ToYearString(day, DateTimeHelper.GetCulture(this))); 
                    childButton.Visibility = Visibility.Visible;
 
                    if (this.Owner != null)
                    {
                        childButton.HasSelectedDays = (Owner.DisplayDate.Year == year);
 
                        if (year < this.Owner.DisplayDateStartInternal.Year || year > this.Owner.DisplayDateEndInternal.Year)
                        { 
                            childButton.IsEnabled = false; 
                            childButton.Opacity = 0;
                        } 
                        else
                        {
                            childButton.IsEnabled = true;
                            childButton.Opacity = 1; 
                        }
                    } 
 
                    // SET IF THE YEAR IS INACTIVE OR NOT: set if the year is a trailing year or not
                    childButton.IsInactive = year < decade || year > decadeEnd; 
                }
                else
                {
                    childButton.DataContext = null; 
                    childButton.IsEnabled = false;
                    childButton.Opacity = 0; 
                } 

                count++; 
            }
        }

        private void SetYearModeMonthButtons() 
        {
            int count = 0; 
            foreach (object child in _yearView.Children) 
            {
                CalendarButton childButton = child as CalendarButton; 
                Debug.Assert(childButton != null);

                // There should be no time component. Time is 12:00 AM
                DateTime day = new DateTime(DisplayDate.Year, count + 1, 1); 
                childButton.DataContext = day;
                childButton.SetContentInternal(DateTimeHelper.ToAbbreviatedMonthString(day, DateTimeHelper.GetCulture(this))); 
                childButton.Visibility = Visibility.Visible; 

                if (this.Owner != null) 
                {
                    Debug.Assert(this.Owner.DisplayDateInternal != null);
                    childButton.HasSelectedDays = (DateTimeHelper.CompareYearMonth(day, this.Owner.DisplayDateInternal) == 0);
 
                    if (DateTimeHelper.CompareYearMonth(day, this.Owner.DisplayDateStartInternal) < 0 || DateTimeHelper.CompareYearMonth(day, this.Owner.DisplayDateEndInternal) > 0)
                    { 
                        childButton.IsEnabled = false; 
                        childButton.Opacity = 0;
                    } 
                    else
                    {
                        childButton.IsEnabled = true;
                        childButton.Opacity = 1; 
                    }
                } 
 
                childButton.IsInactive = false;
                count++; 
            }
        }

        private void SetYearModeHeaderButton() 
        {
            if (this._headerButton != null) 
            { 
                this._headerButton.IsEnabled = true;
                this._headerButton.Content = DateTimeHelper.ToYearString(DisplayDate, DateTimeHelper.GetCulture(this)); 
            }
        }

        private void SetYearModeNextButton() 
        {
            if (this.Owner != null && _nextButton != null) 
            { 
                _nextButton.IsEnabled = (this.Owner.DisplayDateEndInternal.Year != DisplayDate.Year);
            } 
        }

        private void SetYearModePreviousButton()
        { 
            if (this.Owner != null && _previousButton != null)
            { 
                _previousButton.IsEnabled = (this.Owner.DisplayDateStartInternal.Year != DisplayDate.Year); 
            }
        } 

        #endregion Year Mode Display

        #region Decade Mode Display 

        private void SetDecadeModeHeaderButton(int decade) 
        { 
            if (this._headerButton != null)
            { 
                this._headerButton.Content = DateTimeHelper.ToDecadeRangeString(decade, this);
                this._headerButton.IsEnabled = false;
            }
        } 

        private void SetDecadeModeNextButton(int decadeEnd) 
        { 
            if (this.Owner != null && _nextButton != null)
            { 
                _nextButton.IsEnabled = (this.Owner.DisplayDateEndInternal.Year > decadeEnd);
            }
        }
 
        private void SetDecadeModePreviousButton(int decade)
        { 
            if (this.Owner != null && _previousButton != null) 
            {
                _previousButton.IsEnabled = (decade > this.Owner.DisplayDateStartInternal.Year); 
            }
        }

        #endregion Decade Mode Display 

        // How many days of the previous month need to be displayed 
        private int GetNumberOfDisplayedDaysFromPreviousMonth(DateTime firstOfMonth) 
        {
            DayOfWeek day = _calendar.GetDayOfWeek(firstOfMonth); 
            int i;

            if (this.Owner != null)
            { 
                i = ((day - this.Owner.FirstDayOfWeek + NUMBER_OF_DAYS_IN_WEEK) % NUMBER_OF_DAYS_IN_WEEK);
            } 
            else 
            {
                i = ((day - DateTimeHelper.GetDateFormat(DateTimeHelper.GetCulture(this)).FirstDayOfWeek + NUMBER_OF_DAYS_IN_WEEK) % NUMBER_OF_DAYS_IN_WEEK); 
            }

            if (i == 0)
            { 
                return NUMBER_OF_DAYS_IN_WEEK;
            } 
            else 
            {
                return i; 
            }
        }

        ///  
        /// Gets a binding to a property on the owning calendar
        ///  
        ///  
        /// 
        private BindingBase GetOwnerBinding(string propertyName) 
        {
            Binding result = new Binding(propertyName);
            result.Source = this.Owner;
            return result; 
        }
 
        #endregion Private Methods 

        #region Resource Keys 

        /// 
        ///     Resource key for DayTitleTemplate
        ///  
        public static ComponentResourceKey DayTitleTemplateResourceKey
        { 
            get 
            {
                if (_dayTitleTemplateResourceKey == null) 
                {
                    _dayTitleTemplateResourceKey = new ComponentResourceKey(typeof(CalendarItem), ElementDayTitleTemplate);
                }
 
                return _dayTitleTemplateResourceKey;
            } 
        } 

        #endregion 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK