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
- ConnectionPoolManager.cs
- Subtree.cs
- Pair.cs
- DayRenderEvent.cs
- ProtocolElementCollection.cs
- ReferenceCountedObject.cs
- codemethodreferenceexpression.cs
- ErrorStyle.cs
- SamlAuthenticationClaimResource.cs
- UInt32Converter.cs
- Win32PrintDialog.cs
- CustomCredentialPolicy.cs
- XmlNodeReader.cs
- DbProviderServices.cs
- Viewport2DVisual3D.cs
- InvalidPropValue.cs
- MediaSystem.cs
- SoapCodeExporter.cs
- FileVersionInfo.cs
- WindowExtensionMethods.cs
- XmlSchemaInfo.cs
- XamlGridLengthSerializer.cs
- DataServiceExpressionVisitor.cs
- DrawingGroup.cs
- EntitySetDataBindingList.cs
- DataGridViewColumn.cs
- FormViewRow.cs
- WebReferenceOptions.cs
- OracleBoolean.cs
- ValueSerializer.cs
- BamlStream.cs
- ScrollableControl.cs
- TemplatedMailWebEventProvider.cs
- FontSourceCollection.cs
- COM2Enum.cs
- InvokeBase.cs
- ThreadNeutralSemaphore.cs
- GlyphElement.cs
- MinimizableAttributeTypeConverter.cs
- DynamicRouteExpression.cs
- CodeStatementCollection.cs
- XmlTextReaderImpl.cs
- LateBoundChannelParameterCollection.cs
- ProcessThreadCollection.cs
- CompilerInfo.cs
- DocumentSchemaValidator.cs
- ConfigurationPropertyAttribute.cs
- BulletChrome.cs
- ListViewPagedDataSource.cs
- TemplateKeyConverter.cs
- VideoDrawing.cs
- SynthesizerStateChangedEventArgs.cs
- StringAnimationBase.cs
- HttpModuleActionCollection.cs
- StringExpressionSet.cs
- EdmFunction.cs
- DependencyObjectType.cs
- ScaleTransform.cs
- HitTestFilterBehavior.cs
- BindableAttribute.cs
- SetStoryboardSpeedRatio.cs
- PropertyDescriptorCollection.cs
- FrameworkElement.cs
- ToolboxComponentsCreatedEventArgs.cs
- HttpRequestCacheValidator.cs
- ResourceSetExpression.cs
- SkewTransform.cs
- InfiniteTimeSpanConverter.cs
- WebEvents.cs
- CodeObjectCreateExpression.cs
- XmlStreamStore.cs
- PropertyInformationCollection.cs
- DataServiceRequestArgs.cs
- ConfigurationException.cs
- EventLogEntry.cs
- ProgressBarRenderer.cs
- TreeNodeSelectionProcessor.cs
- ValidationSummary.cs
- RecordManager.cs
- PrePrepareMethodAttribute.cs
- RightsManagementPermission.cs
- PersonalizationEntry.cs
- DataTableTypeConverter.cs
- DataSysAttribute.cs
- HttpsHostedTransportConfiguration.cs
- Base64Encoder.cs
- PropertyValueChangedEvent.cs
- PropertyChangeTracker.cs
- BooleanStorage.cs
- MemberDescriptor.cs
- ProviderSettingsCollection.cs
- HostingEnvironmentSection.cs
- QueryContinueDragEventArgs.cs
- VirtualPath.cs
- DataGridViewColumnDesignTimeVisibleAttribute.cs
- Vector3D.cs
- AssemblyNameProxy.cs
- Compilation.cs
- CoTaskMemHandle.cs
- Hex.cs