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
- HorizontalAlignConverter.cs
- GradientBrush.cs
- XamlToRtfWriter.cs
- autovalidator.cs
- TaiwanCalendar.cs
- KeyEventArgs.cs
- IQueryable.cs
- COM2EnumConverter.cs
- DecoderReplacementFallback.cs
- ProfileGroupSettings.cs
- GcHandle.cs
- GeneratedCodeAttribute.cs
- GenericParameterDataContract.cs
- NamespaceDisplay.xaml.cs
- TextParagraph.cs
- PageContent.cs
- SequentialActivityDesigner.cs
- GcSettings.cs
- XmlSchemaGroupRef.cs
- ScriptMethodAttribute.cs
- GridPatternIdentifiers.cs
- InputLanguageManager.cs
- RsaKeyGen.cs
- Vector3DIndependentAnimationStorage.cs
- HttpModulesSection.cs
- TransactionManager.cs
- CompiledRegexRunnerFactory.cs
- ParserHooks.cs
- OperatingSystem.cs
- VBIdentifierNameEditor.cs
- ProxyElement.cs
- HtmlButton.cs
- PageBreakRecord.cs
- AppearanceEditorPart.cs
- HtmlSelect.cs
- OracleCommandSet.cs
- TraceFilter.cs
- EventDescriptorCollection.cs
- CollectionCodeDomSerializer.cs
- Privilege.cs
- TaiwanCalendar.cs
- XamlSerializer.cs
- EdgeModeValidation.cs
- MouseGestureConverter.cs
- SplitterCancelEvent.cs
- AppDomainGrammarProxy.cs
- TimeoutValidationAttribute.cs
- PerformanceCountersElement.cs
- MultipleViewProviderWrapper.cs
- entityreference_tresulttype.cs
- TextProviderWrapper.cs
- SyndicationDeserializer.cs
- MultipleViewProviderWrapper.cs
- SqlTypeSystemProvider.cs
- TimeoutValidationAttribute.cs
- FullTextState.cs
- KeyBinding.cs
- ListDataHelper.cs
- controlskin.cs
- ScriptDescriptor.cs
- TemplatedEditableDesignerRegion.cs
- DetailsViewModeEventArgs.cs
- input.cs
- SamlAssertionDirectKeyIdentifierClause.cs
- EraserBehavior.cs
- BindingList.cs
- EqualityArray.cs
- Animatable.cs
- OracleParameterBinding.cs
- PasswordPropertyTextAttribute.cs
- CallId.cs
- DomNameTable.cs
- SiteMapDesignerDataSourceView.cs
- ClientScriptItemCollection.cs
- DataGridViewRowDividerDoubleClickEventArgs.cs
- SymmetricCryptoHandle.cs
- ProviderConnectionPointCollection.cs
- Int32Animation.cs
- RequestCachePolicyConverter.cs
- VisualTreeHelper.cs
- ListenerUnsafeNativeMethods.cs
- TagNameToTypeMapper.cs
- SspiSecurityTokenParameters.cs
- _ConnectStream.cs
- Win32SafeHandles.cs
- XsltArgumentList.cs
- DataGridColumnCollection.cs
- KeyNotFoundException.cs
- SoapInteropTypes.cs
- XNodeSchemaApplier.cs
- DelayedRegex.cs
- MenuItemCollectionEditorDialog.cs
- ChangesetResponse.cs
- PKCS1MaskGenerationMethod.cs
- SoapEnumAttribute.cs
- SymbolType.cs
- SecurityTokenRequirement.cs
- BooleanAnimationBase.cs
- HwndAppCommandInputProvider.cs
- RoutedUICommand.cs