Reputation: 2715
I have a WPF listbox with it's ItemSource bound to a collection. When the user clicks and drags the selected item over the next item in the listbox I sometimes get an Invalid Operation Exception: "Collection was modified; enumeration operation may not execute".
I've tried setting AllowDrop on the ItemContainerStyle to false, and handling PreviewDragEnter/Leave with e.Handled=true;
but I can still get the crash.
Is there a way to really stop this behaviour? I have no need to move the listbox items around.
Here's my WPF listbox code:
<ListBox ItemsSource="{Binding Conversations}"
SelectedItem="{Binding SelectedConversation}"
VirtualizingStackPanel.IsVirtualizing="True"
PreviewDragEnter="UIElement_OnPreviewDragEnter">
<ListBox.ItemContainerStyle>
<Style BasedOn="{StaticResource MyListBoxItemStyle}" TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="AllowDrop" Value="False"/>
<EventSetter Event="PreviewDragEnter" Handler="UIElement_OnPreviewDragEnter" />
<EventSetter Event="PreviewDragLeave" Handler="UIElement_OnPreviewDragEnter"/>
<EventSetter Event="MouseEnter" Handler="EventSetter_OnHandler"></EventSetter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
And some codebehind:
private void UIElement_OnPreviewDragEnter(object sender, DragEventArgs e)
{
e.Handled = true;
}
private void EventSetter_OnHandler(object sender, MouseEventArgs e)
{
if (e.MouseDevice.LeftButton == MouseButtonState.Pressed)
{
e.Handled = true;
}
}
Here's the exception message
Current_DispatcherUnhandledException : System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
at System.Collections.Generic.List`1.Enumerator.MoveNext()
at System.Windows.Controls.Primitives.Selector.SelectionChanger.CreateDeltaSelectionChange(List`1 unselectedItems, List`1 selectedItems)
at System.Windows.Controls.Primitives.Selector.SelectionChanger.End()
at System.Windows.Controls.Primitives.Selector.SelectionChanger.SelectJustThisItem(ItemInfo info, Boolean assumeInItemsCollection)
at System.Windows.Controls.ListBox.MakeSingleSelection(ListBoxItem listItem)
at System.Windows.Controls.ListBox.MakeKeyboardSelection(ListBoxItem item)
at System.Windows.Controls.ListBox.FocusItem(ItemInfo info, ItemNavigateArgs itemNavigateArgs)
at System.Windows.Controls.ItemsControl.NavigateToItem(Object item, Int32 elementIndex, ItemNavigateArgs itemNavigateArgs, Boolean alwaysAtTopOfViewport)
at System.Windows.Controls.ListBox.NotifyListItemMouseDragged(ListBoxItem listItem)
at System.Windows.Controls.ListBoxItem.OnMouseEnter(MouseEventArgs e)
at System.Windows.UIElement.OnMouseEnterThunk(Object sender, MouseEventArgs e)
at System.Windows.Input.MouseEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e)
at System.Windows.MouseOverProperty.FireNotifications(UIElement uie, ContentElement ce, UIElement3D uie3D, Boolean oldValue)
at System.Windows.ReverseInheritProperty.FirePropertyChangeInAncestry(DependencyObject element, Boolean oldValue, DeferredElementTreeState treeState, Action`2 originChangedAction)
at System.Windows.ReverseInheritProperty.FirePropertyChangeInAncestry(DependencyObject element, Boolean oldValue, DeferredElementTreeState treeState, Action`2 originChangedAction)
at System.Windows.ReverseInheritProperty.FirePropertyChangeInAncestry(DependencyObject element, Boolean oldValue, DeferredElementTreeState treeState, Action`2 originChangedAction)
at System.Windows.ReverseInheritProperty.FirePropertyChangeInAncestry(DependencyObject element, Boolean oldValue, DeferredElementTreeState treeState, Action`2 originChangedAction)
at System.Windows.ReverseInheritProperty.OnOriginValueChanged(DependencyObject oldOrigin, DependencyObject newOrigin, IList`1 otherOrigins, DeferredElementTreeState& oldTreeState, Action`2 originChangedAction)
at System.Windows.Input.MouseDevice.ChangeMouseOver(IInputElement mouseOver, Int32 timestamp)
at System.Windows.Input.MouseDevice.PreNotifyInput(Object sender, NotifyInputEventArgs e)
at System.Windows.Input.InputManager.ProcessStagingArea()
at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
Upvotes: 1
Views: 815
Reputation: 2715
Seems that binding the IsSelected to my model was causing the issue. Removing the binding fixed it and doesn't impact on the UI.
Upvotes: 3
Reputation: 20764
It's most likely because you have somewhere a foreach
loop on Conversations
or another IEnumerable
operation, that is executed, right when you move the listbox items around.
Try synchronizing access to Conversations
Upvotes: 0