dotnet/wpf · error · NotSupportedException

SR.CalendarCollection_MultiThreadedCollectionChangeNotSuppor…

Error message

SR.CalendarCollection_MultiThreadedCollectionChangeNotSupported

What it means

SelectedDatesCollection.ClearItems() throws NotSupportedException when IsValidThread() is false, i.e. a collection-change operation is attempted from a thread other than the thread that owns the Calendar (its Dispatcher thread). WPF Calendar collections only allow mutation on their owning thread.

Solutions

  1. Marshal the mutation to the UI thread with Dispatcher.Invoke/BeginInvoke.
  2. Use async/await with a captured UI SynchronizationContext so continuations run on the Dispatcher thread.
  3. Bind via a ViewModel ObservableCollection updated on the UI thread instead of touching the Calendar collection directly.

Example fix

// before
calendar.SelectedDates.Clear(); // on background thread -> throws
// after
calendar.Dispatcher.Invoke(() => calendar.SelectedDates.Clear());
Defensive patterns

Strategy: try-catch

Validate before calling

if (!calendar.Dispatcher.CheckAccess())
{
    calendar.Dispatcher.Invoke(() => calendar.SelectedDates.Clear());
    return;
}
calendar.SelectedDates.Clear();

Try / catch

try
{
    calendar.SelectedDates.Clear();
}
catch (NotSupportedException)
{
    calendar.Dispatcher.Invoke(() => calendar.SelectedDates.Clear());
}

Prevention

When it happens

Trigger: Calling selectedDates.Clear() (or any collection mutation) on the SelectedDatesCollection of a Calendar from a background/worker thread.

Common situations: Updating calendar selection from a Task, async callback, or timer thread; deserializing data on a worker thread and pushing results directly into the collection.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/a7a5e39238a2d820. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/SelectedDatesCollection.cs:133

            {
                this.Add(current);
            }

            EndAddRange();
        }

        #endregion Public Methods

        #region Protected methods

        /// <summary>
        /// Clears all the items of the SelectedDates.
        /// </summary>
        protected override void ClearItems()
        {
            if (!IsValidThread())
            {
                throw new NotSupportedException(SR.CalendarCollection_MultiThreadedCollectionChangeNotSupported);
            }

            // Turn off highlight
            this._owner.HoverStart = null;

            ClearInternal(true /*fireChangeNotification*/);
        }

        /// <summary>
        /// Inserts the item in the specified position of the SelectedDates collection.
        /// </summary>
        /// <param name="index"></param>
        /// <param name="item"></param>
        protected override void InsertItem(int index, DateTime item)
        {
            if (!IsValidThread())
            {
                throw new NotSupportedException(SR.CalendarCollection_MultiThreadedCollectionChangeNotSupported);

View on GitHub (pinned to 81131a70a4)