Updating ObservableCollection throws an "Parameter is invalid" exception

I have a strange problem that I do not understand. This is in Silverlight / WP7.

I populate an ObservableCollection with elements, and later I want to update each of the elements.

I managed to remove the code to reproduce the error. My XAML is just a ListBox and a button.

private ObservableCollection<int> Words = new ObservableCollection<int>(); public MainPage() { InitializeComponent(); listBox1.ItemsSource = Words; } private void button1_Click(object sender, RoutedEventArgs e) { List<int> numbers = new List<int>() { 1,2,3 }; foreach (var number in numbers) { var index = Words.IndexOf(number); if (index > -1) Words[index] = number; else Words.Add(number); } } 

When you run the code for the first time, it fills the ObservableCollection with numbers 1, 2, and 3, and they appear in the ListBox.

The second time it runs all the code, but then an unhandled exception is thrown with the message "The parameter is incorrect."

The strange thing is that if I delete my line in the constructor, the one where I configured the ItemSource does not throw an error. The observed collection is updated as needed.

Also, if I comment on the line "Words [index] = number", it also works. Therefore, for some reason, when my ObservableCollection is set as the data source for the ListBox, I cannot replace the item.

Can someone explain why? (Or suggest a workaround?)

My decision; I changed the code from

 if (index > -1) Words[index] = number; 

to

 if (index > -1) { Words.RemoveAt(index); Words.Add(number); } 

This made the problem go away.

+4
source share
2 answers

If you enable CLR Exceptons leak on throw (in the "Debug | Exceptions" section) you will see this stack trace:

 mscorlib.dll!System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument argument, System.ExceptionResource resource) + 0x10 bytes mscorlib.dll!System.ThrowHelper.ThrowArgumentOutOfRangeException() + 0x9 bytes mscorlib.dll!System.Collections.Generic.List<object>.this[int].get(int index) + 0xe bytes mscorlib.dll!System.Collections.ObjectModel.Collection<object>.System.Collections.IList.get_Item(int index) + 0x7 bytes System.Windows.dll!System.Windows.Controls.ItemCollection.GetItemImpl(int index) + 0x17 bytes System.Windows.dll!System.Windows.Controls.ItemCollection.GetItemImplSkipMethodPack(int index) + 0x2 bytes System.Windows.dll!System.Windows.PresentationFrameworkCollection<object>.this[int].get(int index) + 0x2 bytes System.Windows.dll!System.Windows.Controls.VirtualizingStackPanel.CleanupContainers(System.Windows.Controls.ItemsControl itemsControl) + 0xa3 bytes System.Windows.dll!System.Windows.Controls.VirtualizingStackPanel.MeasureOverride(System.Windows.Size constraint) + 0x56a bytes System.Windows.dll!System.Windows.FrameworkElement.MeasureOverride(System.IntPtr nativeTarget, float inWidth, float inHeight, out float outWidth, out float outHeight) + 0x45 bytes [External Code] 

For some reason, the stack virtualization panel is trying to clear an element at index -1 (you can see this value for the index in the stack frame).

The content type of the ObservableCollection does not matter. You get the same error with strings ... and this only happens with two elements.

For me, it looks like a bug in VirtualizingStackPanel. You can get around it (if you do not need the virtualization function) by setting the value of the "Virtualization" parameter to "Standard" instead of "Recycling" in the ListBox:

 <ListBox VirtualizingStackPanel.VirtualizationMode="Standard" ... </ListBox> 
+3
source

Alternatively, why not use data binding instead of setting the source element from code?

+2
source

All Articles