Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / SelectedDatesCollection.cs / 1305600 / SelectedDatesCollection.cs
//---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Threading; using System.Windows; namespace System.Windows.Controls { ////// Represents the collection of SelectedDates for the Calendar Control. /// public sealed class SelectedDatesCollection : ObservableCollection{ #region Data private Collection _addedItems; private Collection _removedItems; private Thread _dispatcherThread; private bool _isAddingRange; private Calendar _owner; private DateTime? _maximumDate; private DateTime? _minimumDate; #endregion Data /// /// Initializes a new instance of the CalendarSelectedDatesCollection class. /// /// public SelectedDatesCollection(Calendar owner) { this._dispatcherThread = Thread.CurrentThread; this._owner = owner; this._addedItems = new Collection(); this._removedItems = new Collection (); } #region Internal Properties internal DateTime? MinimumDate { get { if (Count < 1) { return null; } if (!_minimumDate.HasValue) { DateTime result = this[0]; foreach (DateTime selectedDate in this) { if (DateTime.Compare(selectedDate, result) < 0) { result = selectedDate; } } _maximumDate = result; } return _minimumDate; } } internal DateTime? MaximumDate { get { if (Count < 1) { return null; } if (!_maximumDate.HasValue) { DateTime result = this[0]; foreach (DateTime selectedDate in this) { if (DateTime.Compare(selectedDate, result) > 0) { result = selectedDate; } } _maximumDate = result; } return _maximumDate; } } #endregion #region Public methods /// /// Adds a range of dates to the Calendar SelectedDates. /// /// /// public void AddRange(DateTime start, DateTime end) { BeginAddRange(); // 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. if (this._owner.SelectionMode == CalendarSelectionMode.SingleRange && this.Count > 0) { this.ClearInternal(); } foreach (DateTime current in GetDaysInRange(start, end)) { this.Add(current); } EndAddRange(); } #endregion Public Methods #region Protected methods ////// Clears all the items of the SelectedDates. /// protected override void ClearItems() { if (!IsValidThread()) { throw new NotSupportedException(SR.Get(SRID.CalendarCollection_MultiThreadedCollectionChangeNotSupported)); } // Turn off highlight this._owner.HoverStart = null; ClearInternal(true /*fireChangeNotification*/); } ////// Inserts the item in the specified position of the SelectedDates collection. /// /// /// protected override void InsertItem(int index, DateTime item) { if (!IsValidThread()) { throw new NotSupportedException(SR.Get(SRID.CalendarCollection_MultiThreadedCollectionChangeNotSupported)); } if (!this.Contains(item)) { CollectionaddedItems = new Collection (); bool isCleared = CheckSelectionMode(); if (Calendar.IsValidDateSelection(this._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); UpdateMinMax(item); // The event fires after SelectedDate changes if (index == 0 && !(this._owner.SelectedDate.HasValue && DateTime.Compare(this._owner.SelectedDate.Value, item) == 0)) { this._owner.SelectedDate = item; } if (!_isAddingRange) { addedItems.Add(item); RaiseSelectionChanged(this._removedItems, addedItems); this._removedItems.Clear(); int monthDifference = DateTimeHelper.CompareYearMonth(item, this._owner.DisplayDateInternal); if (monthDifference < 2 && monthDifference > -2) { this._owner.UpdateCellItems(); } } else { this._addedItems.Add(item); } } else { throw new ArgumentOutOfRangeException(SR.Get(SRID.Calendar_OnSelectedDateChanged_InvalidValue)); } } } /// /// Removes the item at the specified position. /// /// protected override void RemoveItem(int index) { if (!IsValidThread()) { throw new NotSupportedException(SR.Get(SRID.CalendarCollection_MultiThreadedCollectionChangeNotSupported)); } if (index >= this.Count) { base.RemoveItem(index); ClearMinMax(); } else { CollectionaddedItems = new Collection (); Collection removedItems = new Collection (); int monthDifference = DateTimeHelper.CompareYearMonth(this[index], this._owner.DisplayDateInternal); removedItems.Add(this[index]); base.RemoveItem(index); ClearMinMax(); // The event fires after SelectedDate changes if (index == 0) { if (Count > 0) { this._owner.SelectedDate = this[0]; } else { this._owner.SelectedDate = null; } } RaiseSelectionChanged(removedItems, addedItems); if (monthDifference < 2 && monthDifference > -2) { this._owner.UpdateCellItems(); } } } /// /// The object in the specified index is replaced with the provided item. /// /// /// protected override void SetItem(int index, DateTime item) { if (!IsValidThread()) { throw new NotSupportedException(SR.Get(SRID.CalendarCollection_MultiThreadedCollectionChangeNotSupported)); } if (!this.Contains(item)) { CollectionaddedItems = new Collection (); Collection removedItems = new Collection (); if (index >= this.Count) { base.SetItem(index, item); UpdateMinMax(item); } else { if (item != null && DateTime.Compare(this[index], item) != 0 && Calendar.IsValidDateSelection(this._owner, item)) { removedItems.Add(this[index]); base.SetItem(index, item); UpdateMinMax(item); addedItems.Add(item); // The event fires after SelectedDate changes if (index == 0 && !(this._owner.SelectedDate.HasValue && DateTime.Compare(this._owner.SelectedDate.Value, item) == 0)) { this._owner.SelectedDate = item; } RaiseSelectionChanged(removedItems, addedItems); int monthDifference = DateTimeHelper.CompareYearMonth(item, this._owner.DisplayDateInternal); if (monthDifference < 2 && monthDifference > -2) { this._owner.UpdateCellItems(); } } } } } #endregion Protected methods #region Internal Methods /// /// Adds a range of dates to the Calendar SelectedDates. /// ////// Helper version of AddRange for mouse drag selection. /// This version guarantees no exceptions will be thrown by removing blackout days from the range before adding to the collection /// internal void AddRangeInternal(DateTime start, DateTime end) { BeginAddRange(); // 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 DateTime lastAddedDate = start; foreach (DateTime current in GetDaysInRange(start, end)) { if (Calendar.IsValidDateSelection(this._owner, current)) { this.Add(current); lastAddedDate = current; } else { if (this._owner.SelectionMode == CalendarSelectionMode.SingleRange) { this._owner.CurrentDate = lastAddedDate; break; } } } EndAddRange(); } internal void ClearInternal() { ClearInternal(false /*fireChangeNotification*/); } internal void ClearInternal(bool fireChangeNotification) { if (this.Count > 0) { foreach (DateTime item in this) { _removedItems.Add(item); } base.ClearItems(); ClearMinMax(); if (fireChangeNotification) { if (this._owner.SelectedDate != null) { this._owner.SelectedDate = null; } if (_removedItems.Count > 0) { CollectionaddedItems = new Collection (); RaiseSelectionChanged(_removedItems, addedItems); _removedItems.Clear(); } this._owner.UpdateCellItems(); } } } internal void Toggle(DateTime date) { if (Calendar.IsValidDateSelection(this._owner, date)) { switch (this._owner.SelectionMode) { case CalendarSelectionMode.SingleDate: { if (!this._owner.SelectedDate.HasValue || DateTimeHelper.CompareDays(this._owner.SelectedDate.Value, date) != 0) { this._owner.SelectedDate = date; } else { this._owner.SelectedDate = null; } break; } case CalendarSelectionMode.MultipleRange: { if (!Remove(date)) { Add(date); } break; } default: { Debug.Assert(false); break; } } } } #endregion Internal Methods #region Private Methods private void RaiseSelectionChanged(IList removedItems, IList addedItems) { this._owner.OnSelectedDatesCollectionChanged(new CalendarSelectionChangedEventArgs(Calendar.SelectedDatesChangedEvent, removedItems, addedItems)); } private void BeginAddRange() { Debug.Assert(!_isAddingRange); _isAddingRange = true; } private void EndAddRange() { Debug.Assert(_isAddingRange); _isAddingRange = false; RaiseSelectionChanged(this._removedItems, this._addedItems); this._removedItems.Clear(); this._addedItems.Clear(); this._owner.UpdateCellItems(); } private bool CheckSelectionMode() { if (this._owner.SelectionMode == CalendarSelectionMode.None) { throw new InvalidOperationException(SR.Get(SRID.Calendar_OnSelectedDateChanged_InvalidOperation)); } if (this._owner.SelectionMode == CalendarSelectionMode.SingleDate && this.Count > 0) { throw new InvalidOperationException(SR.Get(SRID.Calendar_CheckSelectionMode_InvalidOperation)); } // if user tries to add an item into the SelectedDates in SingleRange mode, we 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 (this._owner.SelectionMode == CalendarSelectionMode.SingleRange && !_isAddingRange && this.Count > 0) { this.ClearInternal(); return true; } else { return false; } } private bool IsValidThread() { return Thread.CurrentThread == this._dispatcherThread; } private void UpdateMinMax(DateTime date) { if ((!_maximumDate.HasValue) || (date > _maximumDate.Value)) { _maximumDate = date; } if ((!_minimumDate.HasValue) || (date < _minimumDate.Value)) { _minimumDate = date; } } private void ClearMinMax() { _maximumDate = null; _minimumDate = null; } private static IEnumerable GetDaysInRange(DateTime start, DateTime end) { // 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 = GetDirection(start, end); DateTime? rangeStart = start; do { yield return rangeStart.Value; rangeStart = DateTimeHelper.AddDays(rangeStart.Value, increment); } while (rangeStart.HasValue && DateTime.Compare(end, rangeStart.Value) != -increment); } private static int GetDirection(DateTime start, DateTime end) { return (DateTime.Compare(end, start) >= 0) ? 1 : -1; } #endregion Private Methods } } // 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; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Threading; using System.Windows; namespace System.Windows.Controls { /// /// Represents the collection of SelectedDates for the Calendar Control. /// public sealed class SelectedDatesCollection : ObservableCollection{ #region Data private Collection _addedItems; private Collection _removedItems; private Thread _dispatcherThread; private bool _isAddingRange; private Calendar _owner; private DateTime? _maximumDate; private DateTime? _minimumDate; #endregion Data /// /// Initializes a new instance of the CalendarSelectedDatesCollection class. /// /// public SelectedDatesCollection(Calendar owner) { this._dispatcherThread = Thread.CurrentThread; this._owner = owner; this._addedItems = new Collection(); this._removedItems = new Collection (); } #region Internal Properties internal DateTime? MinimumDate { get { if (Count < 1) { return null; } if (!_minimumDate.HasValue) { DateTime result = this[0]; foreach (DateTime selectedDate in this) { if (DateTime.Compare(selectedDate, result) < 0) { result = selectedDate; } } _maximumDate = result; } return _minimumDate; } } internal DateTime? MaximumDate { get { if (Count < 1) { return null; } if (!_maximumDate.HasValue) { DateTime result = this[0]; foreach (DateTime selectedDate in this) { if (DateTime.Compare(selectedDate, result) > 0) { result = selectedDate; } } _maximumDate = result; } return _maximumDate; } } #endregion #region Public methods /// /// Adds a range of dates to the Calendar SelectedDates. /// /// /// public void AddRange(DateTime start, DateTime end) { BeginAddRange(); // 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. if (this._owner.SelectionMode == CalendarSelectionMode.SingleRange && this.Count > 0) { this.ClearInternal(); } foreach (DateTime current in GetDaysInRange(start, end)) { this.Add(current); } EndAddRange(); } #endregion Public Methods #region Protected methods ////// Clears all the items of the SelectedDates. /// protected override void ClearItems() { if (!IsValidThread()) { throw new NotSupportedException(SR.Get(SRID.CalendarCollection_MultiThreadedCollectionChangeNotSupported)); } // Turn off highlight this._owner.HoverStart = null; ClearInternal(true /*fireChangeNotification*/); } ////// Inserts the item in the specified position of the SelectedDates collection. /// /// /// protected override void InsertItem(int index, DateTime item) { if (!IsValidThread()) { throw new NotSupportedException(SR.Get(SRID.CalendarCollection_MultiThreadedCollectionChangeNotSupported)); } if (!this.Contains(item)) { CollectionaddedItems = new Collection (); bool isCleared = CheckSelectionMode(); if (Calendar.IsValidDateSelection(this._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); UpdateMinMax(item); // The event fires after SelectedDate changes if (index == 0 && !(this._owner.SelectedDate.HasValue && DateTime.Compare(this._owner.SelectedDate.Value, item) == 0)) { this._owner.SelectedDate = item; } if (!_isAddingRange) { addedItems.Add(item); RaiseSelectionChanged(this._removedItems, addedItems); this._removedItems.Clear(); int monthDifference = DateTimeHelper.CompareYearMonth(item, this._owner.DisplayDateInternal); if (monthDifference < 2 && monthDifference > -2) { this._owner.UpdateCellItems(); } } else { this._addedItems.Add(item); } } else { throw new ArgumentOutOfRangeException(SR.Get(SRID.Calendar_OnSelectedDateChanged_InvalidValue)); } } } /// /// Removes the item at the specified position. /// /// protected override void RemoveItem(int index) { if (!IsValidThread()) { throw new NotSupportedException(SR.Get(SRID.CalendarCollection_MultiThreadedCollectionChangeNotSupported)); } if (index >= this.Count) { base.RemoveItem(index); ClearMinMax(); } else { CollectionaddedItems = new Collection (); Collection removedItems = new Collection (); int monthDifference = DateTimeHelper.CompareYearMonth(this[index], this._owner.DisplayDateInternal); removedItems.Add(this[index]); base.RemoveItem(index); ClearMinMax(); // The event fires after SelectedDate changes if (index == 0) { if (Count > 0) { this._owner.SelectedDate = this[0]; } else { this._owner.SelectedDate = null; } } RaiseSelectionChanged(removedItems, addedItems); if (monthDifference < 2 && monthDifference > -2) { this._owner.UpdateCellItems(); } } } /// /// The object in the specified index is replaced with the provided item. /// /// /// protected override void SetItem(int index, DateTime item) { if (!IsValidThread()) { throw new NotSupportedException(SR.Get(SRID.CalendarCollection_MultiThreadedCollectionChangeNotSupported)); } if (!this.Contains(item)) { CollectionaddedItems = new Collection (); Collection removedItems = new Collection (); if (index >= this.Count) { base.SetItem(index, item); UpdateMinMax(item); } else { if (item != null && DateTime.Compare(this[index], item) != 0 && Calendar.IsValidDateSelection(this._owner, item)) { removedItems.Add(this[index]); base.SetItem(index, item); UpdateMinMax(item); addedItems.Add(item); // The event fires after SelectedDate changes if (index == 0 && !(this._owner.SelectedDate.HasValue && DateTime.Compare(this._owner.SelectedDate.Value, item) == 0)) { this._owner.SelectedDate = item; } RaiseSelectionChanged(removedItems, addedItems); int monthDifference = DateTimeHelper.CompareYearMonth(item, this._owner.DisplayDateInternal); if (monthDifference < 2 && monthDifference > -2) { this._owner.UpdateCellItems(); } } } } } #endregion Protected methods #region Internal Methods /// /// Adds a range of dates to the Calendar SelectedDates. /// ////// Helper version of AddRange for mouse drag selection. /// This version guarantees no exceptions will be thrown by removing blackout days from the range before adding to the collection /// internal void AddRangeInternal(DateTime start, DateTime end) { BeginAddRange(); // 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 DateTime lastAddedDate = start; foreach (DateTime current in GetDaysInRange(start, end)) { if (Calendar.IsValidDateSelection(this._owner, current)) { this.Add(current); lastAddedDate = current; } else { if (this._owner.SelectionMode == CalendarSelectionMode.SingleRange) { this._owner.CurrentDate = lastAddedDate; break; } } } EndAddRange(); } internal void ClearInternal() { ClearInternal(false /*fireChangeNotification*/); } internal void ClearInternal(bool fireChangeNotification) { if (this.Count > 0) { foreach (DateTime item in this) { _removedItems.Add(item); } base.ClearItems(); ClearMinMax(); if (fireChangeNotification) { if (this._owner.SelectedDate != null) { this._owner.SelectedDate = null; } if (_removedItems.Count > 0) { CollectionaddedItems = new Collection (); RaiseSelectionChanged(_removedItems, addedItems); _removedItems.Clear(); } this._owner.UpdateCellItems(); } } } internal void Toggle(DateTime date) { if (Calendar.IsValidDateSelection(this._owner, date)) { switch (this._owner.SelectionMode) { case CalendarSelectionMode.SingleDate: { if (!this._owner.SelectedDate.HasValue || DateTimeHelper.CompareDays(this._owner.SelectedDate.Value, date) != 0) { this._owner.SelectedDate = date; } else { this._owner.SelectedDate = null; } break; } case CalendarSelectionMode.MultipleRange: { if (!Remove(date)) { Add(date); } break; } default: { Debug.Assert(false); break; } } } } #endregion Internal Methods #region Private Methods private void RaiseSelectionChanged(IList removedItems, IList addedItems) { this._owner.OnSelectedDatesCollectionChanged(new CalendarSelectionChangedEventArgs(Calendar.SelectedDatesChangedEvent, removedItems, addedItems)); } private void BeginAddRange() { Debug.Assert(!_isAddingRange); _isAddingRange = true; } private void EndAddRange() { Debug.Assert(_isAddingRange); _isAddingRange = false; RaiseSelectionChanged(this._removedItems, this._addedItems); this._removedItems.Clear(); this._addedItems.Clear(); this._owner.UpdateCellItems(); } private bool CheckSelectionMode() { if (this._owner.SelectionMode == CalendarSelectionMode.None) { throw new InvalidOperationException(SR.Get(SRID.Calendar_OnSelectedDateChanged_InvalidOperation)); } if (this._owner.SelectionMode == CalendarSelectionMode.SingleDate && this.Count > 0) { throw new InvalidOperationException(SR.Get(SRID.Calendar_CheckSelectionMode_InvalidOperation)); } // if user tries to add an item into the SelectedDates in SingleRange mode, we 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 (this._owner.SelectionMode == CalendarSelectionMode.SingleRange && !_isAddingRange && this.Count > 0) { this.ClearInternal(); return true; } else { return false; } } private bool IsValidThread() { return Thread.CurrentThread == this._dispatcherThread; } private void UpdateMinMax(DateTime date) { if ((!_maximumDate.HasValue) || (date > _maximumDate.Value)) { _maximumDate = date; } if ((!_minimumDate.HasValue) || (date < _minimumDate.Value)) { _minimumDate = date; } } private void ClearMinMax() { _maximumDate = null; _minimumDate = null; } private static IEnumerable GetDaysInRange(DateTime start, DateTime end) { // 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 = GetDirection(start, end); DateTime? rangeStart = start; do { yield return rangeStart.Value; rangeStart = DateTimeHelper.AddDays(rangeStart.Value, increment); } while (rangeStart.HasValue && DateTime.Compare(end, rangeStart.Value) != -increment); } private static int GetDirection(DateTime start, DateTime end) { return (DateTime.Compare(end, start) >= 0) ? 1 : -1; } #endregion Private Methods } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TypeSystemHelpers.cs
- InkCanvasFeedbackAdorner.cs
- JapaneseCalendar.cs
- RowsCopiedEventArgs.cs
- Operand.cs
- HtmlTitle.cs
- RbTree.cs
- TraceContextEventArgs.cs
- InstanceNormalEvent.cs
- Tracking.cs
- DBConcurrencyException.cs
- ConfigsHelper.cs
- sqlstateclientmanager.cs
- CqlBlock.cs
- HttpRequestWrapper.cs
- EntityExpressionVisitor.cs
- RewritingPass.cs
- EditorZone.cs
- DeclaredTypeElementCollection.cs
- BufferModesCollection.cs
- EdmConstants.cs
- RewritingPass.cs
- OLEDB_Enum.cs
- Decorator.cs
- SqlServer2KCompatibilityAnnotation.cs
- ErrorFormatter.cs
- HwndSourceKeyboardInputSite.cs
- GridViewActionList.cs
- cryptoapiTransform.cs
- MultiTargetingUtil.cs
- UserPreferenceChangingEventArgs.cs
- FrameworkContextData.cs
- XPathParser.cs
- DesignerDataStoredProcedure.cs
- AccessDataSourceView.cs
- CompositeTypefaceMetrics.cs
- ExcludeFromCodeCoverageAttribute.cs
- BuildProvider.cs
- BindMarkupExtensionSerializer.cs
- UIElementCollection.cs
- NullableDecimalMinMaxAggregationOperator.cs
- PersonalizableTypeEntry.cs
- GeneratedCodeAttribute.cs
- OleDbInfoMessageEvent.cs
- ModuleBuilderData.cs
- AccessDataSource.cs
- KerberosSecurityTokenProvider.cs
- SingleAnimationUsingKeyFrames.cs
- LinkAreaEditor.cs
- TransactionState.cs
- CollectionViewSource.cs
- milrender.cs
- NameSpaceExtractor.cs
- ExpressionEditorAttribute.cs
- SafeTokenHandle.cs
- NavigationWindowAutomationPeer.cs
- OracleBFile.cs
- BufferedReceiveElement.cs
- Rule.cs
- TemplateControl.cs
- WmlValidationSummaryAdapter.cs
- AccessDataSourceView.cs
- OleDbStruct.cs
- DataDocumentXPathNavigator.cs
- HtmlControlAdapter.cs
- ForeignKeyConstraint.cs
- DbConnectionPool.cs
- FactoryId.cs
- MulticastNotSupportedException.cs
- ToolTipAutomationPeer.cs
- MonitoringDescriptionAttribute.cs
- BindingList.cs
- TraceEventCache.cs
- UserControlAutomationPeer.cs
- FixedPageProcessor.cs
- CryptoHandle.cs
- Input.cs
- RuntimeCompatibilityAttribute.cs
- CodeMemberProperty.cs
- ISO2022Encoding.cs
- ToolboxItemCollection.cs
- HostVisual.cs
- PasswordRecovery.cs
- WebPartsPersonalization.cs
- FormViewPageEventArgs.cs
- MenuItemAutomationPeer.cs
- HttpProfileGroupBase.cs
- RequiredFieldValidator.cs
- DataGridComboBoxColumn.cs
- ToolStripCollectionEditor.cs
- XLinq.cs
- coordinator.cs
- MemberInfoSerializationHolder.cs
- HtmlElement.cs
- ListViewCancelEventArgs.cs
- TdsEnums.cs
- XmlSchemaSimpleContent.cs
- ApplicationManager.cs
- XmlResolver.cs
- XmlCollation.cs