/// <summary>
        /// Inserts an item into the collection at the specified index.
        /// </summary>
        /// <param name="index">
        /// The zero-based index at which item should be inserted.
        /// </param>
        /// <param name="item">The object to insert.</param>
        /// <remarks>
        /// This implementation raises the CollectionChanged event.
        /// </remarks>
        protected override void InsertItem(int index, DateTime item)
        {
            if (!IsValidThread())
            {
                throw new NotSupportedException(System.Windows.Controls.Properties.Resources.CalendarCollection_MultiThreadedCollectionChangeNotSupported);
            }

            if (!Contains(item))
            {
                Collection <DateTime> addedItems = new Collection <DateTime>();

                if (CheckSelectionMode())
                {
                    if (CalendarEx.IsValidDateSelection(_owner, item))
                    {
                        // If the Collection is cleared since it is SingleRange
                        // and it had another range set the index to 0
                        if (_isCleared)
                        {
                            index      = 0;
                            _isCleared = false;
                        }

                        base.InsertItem(index, item);

                        // The event fires after SelectedDate changes
                        if (index == 0 && !(_owner.SelectedDate.HasValue && DateTime.Compare(_owner.SelectedDate.Value, item) == 0))
                        {
                            _owner.SelectedDate = item;
                        }

                        if (!_isRangeAdded)
                        {
                            addedItems.Add(item);

                            _owner.OnSelectedDatesCollectionChanged(new SelectionChangedEventArgs(_owner.RemovedItems, addedItems));
                            _owner.RemovedItems.Clear();
                            int monthDifference = DateTimeHelper.CompareYearMonth(item, _owner.DisplayDateInternal);

                            if (monthDifference < 2 && monthDifference > -2)
                            {
                                _owner.UpdateMonths();
                            }
                        }
                        else
                        {
                            _addedItems.Add(item);
                        }
                    }
                    else
                    {
                        throw new ArgumentOutOfRangeException(System.Windows.Controls.Properties.Resources.Calendar_OnSelectedDateChanged_InvalidValue);
                    }
                }
            }
        }
        /// <summary>
        /// Replaces the element at the specified index.
        /// </summary>
        /// <param name="index">
        /// The zero-based index of the element to replace.
        /// </param>
        /// <param name="item">
        /// The new value for the element at the specified index.
        /// </param>
        /// <remarks>
        /// This implementation raises the CollectionChanged event.
        /// </remarks>
        protected override void SetItem(int index, DateTime item)
        {
            if (!IsValidThread())
            {
                throw new NotSupportedException(System.Windows.Controls.Properties.Resources.CalendarCollection_MultiThreadedCollectionChangeNotSupported);
            }

            if (!Contains(item))
            {
                Collection <DateTime> addedItems   = new Collection <DateTime>();
                Collection <DateTime> removedItems = new Collection <DateTime>();

                if (index >= Count)
                {
                    base.SetItem(index, item);
                }
                else
                {
                    if (item != null && DateTime.Compare(this[index], item) != 0 && CalendarEx.IsValidDateSelection(_owner, item))
                    {
                        removedItems.Add(this[index]);
                        base.SetItem(index, item);
                        addedItems.Add(item);

                        // The event fires after SelectedDate changes
                        if (index == 0 && !(_owner.SelectedDate.HasValue && DateTime.Compare(_owner.SelectedDate.Value, item) == 0))
                        {
                            _owner.SelectedDate = item;
                        }
                        _owner.OnSelectedDatesCollectionChanged(new SelectionChangedEventArgs(removedItems, addedItems));

                        int monthDifference = DateTimeHelper.CompareYearMonth(item, _owner.DisplayDateInternal);

                        if (monthDifference < 2 && monthDifference > -2)
                        {
                            _owner.UpdateMonths();
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Adds all the dates in the specified range, which includes the first
        /// and last dates, to the collection.
        /// </summary>
        /// <param name="start">The first date to add to the collection.</param>
        /// <param name="end">The last date to add to the collection.</param>
        public void AddRange(DateTime start, DateTime end)
        {
            DateTime?rangeStart;

            // increment parameter specifies if the Days were selected in
            // Descending order or Ascending order based on this value, we add
            // the days in the range either in Ascending order or in Descending
            // order
            int increment = (DateTime.Compare(end, start) >= 0) ? 1 : -1;

            _addedItems.Clear();

            rangeStart    = start;
            _isRangeAdded = true;

            if (_owner.IsMouseSelection)
            {
                // In Mouse Selection we allow the user to be able to add
                // multiple ranges in one action in MultipleRange Mode.  In
                // SingleRange Mode, we only add the first selected range.
                while (rangeStart.HasValue && DateTime.Compare(end, rangeStart.Value) != -increment)
                {
                    if (CalendarEx.IsValidDateSelection(_owner, rangeStart))
                    {
                        Add(rangeStart.Value);
                    }
                    else
                    {
                        if (_owner.SelectionMode == CalendarExSelectionMode.SingleRange)
                        {
                            _owner.HoverEnd = rangeStart.Value.AddDays(-increment);
                            break;
                        }
                    }

                    rangeStart = DateTimeHelper.AddDays(rangeStart.Value, increment);
                }
            }
            else
            {
                // If CalendarSelectionMode.SingleRange and a user
                // programmatically tries to add multiple ranges, we will throw
                // away the old range and replace it with the new one.  In order
                // to provide the removed items without an additional event, we
                // are calling ClearInternal
                if (_owner.SelectionMode == CalendarExSelectionMode.SingleRange && Count > 0)
                {
                    foreach (DateTime item in this)
                    {
                        _owner.RemovedItems.Add(item);
                    }
                    ClearInternal();
                }

                while (rangeStart.HasValue && DateTime.Compare(end, rangeStart.Value) != -increment)
                {
                    Add(rangeStart.Value);
                    rangeStart = DateTimeHelper.AddDays(rangeStart.Value, increment);
                }
            }

            _owner.OnSelectedDatesCollectionChanged(new SelectionChangedEventArgs(_owner.RemovedItems, _addedItems));
            _owner.RemovedItems.Clear();
            _owner.UpdateMonths();
            _isRangeAdded = false;
        }