Code:
/ 4.0 / 4.0 / untmp / 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.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ListBoxAutomationPeer.cs
- ITreeGenerator.cs
- BoundColumn.cs
- SrgsText.cs
- XmlSchemaAnnotation.cs
- Lock.cs
- SystemIPv6InterfaceProperties.cs
- _DomainName.cs
- BatchParser.cs
- MessageOperationFormatter.cs
- KeyGestureConverter.cs
- HtmlValidationSummaryAdapter.cs
- RecordsAffectedEventArgs.cs
- UnionCodeGroup.cs
- FrameworkContextData.cs
- Label.cs
- ScheduleChanges.cs
- NegotiationTokenAuthenticatorState.cs
- DESCryptoServiceProvider.cs
- WebPartDeleteVerb.cs
- RijndaelCryptoServiceProvider.cs
- regiisutil.cs
- ToolStripArrowRenderEventArgs.cs
- ChannelPool.cs
- CodeBlockBuilder.cs
- oledbmetadatacollectionnames.cs
- BuildResult.cs
- DynamicDiscoveryDocument.cs
- UnsafeNativeMethodsPenimc.cs
- Solver.cs
- EventSetter.cs
- IItemProperties.cs
- Parameter.cs
- Header.cs
- ConfigurationValidatorBase.cs
- DataGridViewTextBoxCell.cs
- IHttpResponseInternal.cs
- FixedSOMContainer.cs
- FilteredDataSetHelper.cs
- TextDpi.cs
- RotateTransform3D.cs
- Unit.cs
- HwndStylusInputProvider.cs
- Attributes.cs
- MultipartContentParser.cs
- PropertyKey.cs
- ToolStripDropDownClosingEventArgs.cs
- CodeCatchClause.cs
- DataGridViewTextBoxCell.cs
- TypeUtil.cs
- XmlSerializerAssemblyAttribute.cs
- GZipDecoder.cs
- CodeTypeDeclarationCollection.cs
- KeyValuePairs.cs
- SelectionService.cs
- SegmentInfo.cs
- RealizationDrawingContextWalker.cs
- HtmlFormWrapper.cs
- PlanCompiler.cs
- HttpRuntimeSection.cs
- PartialToken.cs
- BamlLocalizabilityResolver.cs
- COM2ExtendedUITypeEditor.cs
- AnimationLayer.cs
- DoubleIndependentAnimationStorage.cs
- HtmlDocument.cs
- ReliableReplySessionChannel.cs
- StylusPointCollection.cs
- AssociatedControlConverter.cs
- DesignerActionList.cs
- ObjectAnimationBase.cs
- EmptyReadOnlyDictionaryInternal.cs
- PersonalizationProviderCollection.cs
- MarginsConverter.cs
- AuthorizationRule.cs
- MeshGeometry3D.cs
- DesignerSerializationOptionsAttribute.cs
- RuntimeIdentifierPropertyAttribute.cs
- RuntimeWrappedException.cs
- OpacityConverter.cs
- BoolLiteral.cs
- BinaryEditor.cs
- InstanceDescriptor.cs
- SafeLibraryHandle.cs
- ReadOnlyPropertyMetadata.cs
- invalidudtexception.cs
- EntityContainerAssociationSetEnd.cs
- DataGridTableCollection.cs
- PersonalizationState.cs
- ProgressBar.cs
- Calendar.cs
- SpeechSynthesizer.cs
- XsdValidatingReader.cs
- LogStore.cs
- XmlUtf8RawTextWriter.cs
- MULTI_QI.cs
- securitymgrsite.cs
- EdmRelationshipNavigationPropertyAttribute.cs
- TextSimpleMarkerProperties.cs
- ScriptingRoleServiceSection.cs