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
- MergeLocalizationDirectives.cs
- SmtpClient.cs
- __FastResourceComparer.cs
- _CommandStream.cs
- QueryOperationResponseOfT.cs
- GlyphRunDrawing.cs
- OdbcPermission.cs
- SpinLock.cs
- ComponentChangedEvent.cs
- storagemappingitemcollection.viewdictionary.cs
- CleanUpVirtualizedItemEventArgs.cs
- Assign.cs
- FillBehavior.cs
- TypeReference.cs
- AppDomainUnloadedException.cs
- FileUpload.cs
- MenuEventArgs.cs
- SmtpCommands.cs
- DefaultMergeHelper.cs
- EventDescriptor.cs
- RemoteCryptoRsaServiceProvider.cs
- NullableIntAverageAggregationOperator.cs
- TransformCollection.cs
- RegexParser.cs
- TypeHelpers.cs
- EventProviderWriter.cs
- DefaultAutoFieldGenerator.cs
- DataListItemEventArgs.cs
- PerformanceCountersElement.cs
- MutexSecurity.cs
- HttpCookie.cs
- DbgUtil.cs
- SessionPageStateSection.cs
- AssemblyHelper.cs
- SafeHandle.cs
- VisualStateChangedEventArgs.cs
- CachedCompositeFamily.cs
- TransformedBitmap.cs
- BigInt.cs
- SystemNetworkInterface.cs
- EntityContainer.cs
- ModifiableIteratorCollection.cs
- HostingEnvironmentSection.cs
- UriSchemeKeyedCollection.cs
- NonParentingControl.cs
- ExpressionConverter.cs
- WithParamAction.cs
- CodeTypeDeclarationCollection.cs
- HttpHandlerActionCollection.cs
- ServiceTimeoutsBehavior.cs
- FixedSOMGroup.cs
- SmiConnection.cs
- DecoderFallbackWithFailureFlag.cs
- TextDecorationCollection.cs
- StrokeNodeOperations.cs
- ParallelEnumerableWrapper.cs
- ConditionalWeakTable.cs
- LeafCellTreeNode.cs
- MarkerProperties.cs
- TypeLoadException.cs
- CodeFieldReferenceExpression.cs
- EntityParameter.cs
- PersonalizableTypeEntry.cs
- KeyGestureConverter.cs
- WindowsSolidBrush.cs
- TimeSpan.cs
- StyleTypedPropertyAttribute.cs
- log.cs
- SecurityTokenRequirement.cs
- SelfIssuedSamlTokenFactory.cs
- BinaryFormatterWriter.cs
- SignerInfo.cs
- MtomMessageEncodingElement.cs
- ContainerSelectorBehavior.cs
- DropDownList.cs
- XPathNodeHelper.cs
- ListSourceHelper.cs
- SessionPageStateSection.cs
- IfElseDesigner.xaml.cs
- mediaclock.cs
- Converter.cs
- BitSet.cs
- TokenFactoryBase.cs
- CodeNamespace.cs
- DSACryptoServiceProvider.cs
- BitmapEffectInput.cs
- SplayTreeNode.cs
- SafeSystemMetrics.cs
- CompilationSection.cs
- ControlEvent.cs
- SimpleColumnProvider.cs
- ToolStripProgressBar.cs
- ExtentKey.cs
- WeakRefEnumerator.cs
- PhysicalFontFamily.cs
- KerberosRequestorSecurityToken.cs
- InteropEnvironment.cs
- FigureParaClient.cs
- EmptyControlCollection.cs
- WindowsListView.cs