Reputation: 1406
I have a WFP application with a ListBox
and a Button
:
<Window x:Class="UITester.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Title="MainWindow" Height="350" Width="525">
<ListBox Name="list"></ListBox>
<Button Click="ButtonSelect_OnClick">Select Stuff</Button>
</Window>
In the code behind I have this:
public partial class MainWindow : Window
{
private readonly Dictionary<int, int> _selected = new Dictionary<int, int>();
public MainWindow()
{
InitializeComponent();
list.ItemsSource = _selected.Values;
}
private void ButtonSelect_OnClick(object sender, RoutedEventArgs e)
{
_selected.Clear();
for (int i = 0; i < 4; ++i)
{
_selected.Add(i, i);
}
list.Items.Refresh();
}
}
If I run the application without a debugger attached everything seems all right - I click the button and the number 0 to 3 appear in the list.
However, if I run this with a debugger attached I see that when calling the line list.Items.Refresh();
there's an exception thrown:
Collection was modified; enumeration operation may not execute.
As far as I know, this exception is thrown when trying to change a collection while enumerating it. But I'm pretty sure this isn't the case. Everything here happens in the UI thread. First I add elements to the dictionary and only once that's done, I refresh the items in the list box. It seems to me that nothing is changed and in fact, nothing is enumerated.
I suppose that the Refresh
method enumerates the dictionary's values, but they have already been updated and are not changed during this enumeration.
I know this is not the best way to update a ListBox
, but it's part of a much larger and older code, and I just want to understand what's wrong here.
UPDATE
When I change _selected
to be List<int>
and set list.ItemsSource = _selected;
then there's no exception and no warnings in the output window. But when I set _selected
to be 'HashSet` then the problems come back.
Upvotes: 3
Views: 551
Reputation: 1406
This is not a complete answer, since I still don't understand why this happens and what's going on under the hood, but I have convinced myself that I shouldn't be worried about this. The exception occurres deep inside the WPF framework and is probably caught somewhere there. I can only see there's an exception when running with a debugger by looking at the output window:
A first chance exception of type 'System.InvalidOperationException' occurred in mscorlib.dll
And only if I choose to break when the exception is thrown then the debugger indeed breaks. There are no unhandled exceptions.
So while the real reason for this is still a mystery, it would seem that the problem is not in my code...
Upvotes: 1
Reputation: 5262
It would be better to maintain your own list separate from the Dictionary
and copy values over when the Dictionary
changes. I'd advise using an ObservableCollection
, so you don't have to do a refresh call.
I swear I still have my code for an ObservableDictionary
somewhere.
Upvotes: 0