4

我有一个奇怪的问题,我不明白。这是在Silverlight/WP7中。更新ObservableCollection导致“参数不正确”异常

我正在用项目填充ObservableCollection,后来我想更新每个项目。

我设法剥离代码来重现错误。我的XAML只是一个ListBox和一个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); 
     } 
    } 

我第一次运行代码时,它用数字1,2和3填充ObservableCollection,并将它们显示在列表框中。

第二次运行所有的代码被执行,但是随后出现一个带有“The parameter is incorrect”消息的未处理的异常。

奇怪的是,如果我在构造函数中删除我的行,那么我设置ItemsSource的行就不会抛出错误。可观察的集合会根据情况进行更新。

此外,如果我注释掉“Words [index] = number”这一行,它也可以工作。因此,出于某种原因,当我的ObservableCollection被设置为ListBox的数据源时,我无法替换该项目。

有人可以解释为什么吗? (或建议解决方法?)

我的解决方案; 我改变了我的代码隐藏从

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

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

这使问题消失。

回答

3

如果启用CLR Exceptons时抛出突破(下调试|例外),你会看到该堆栈跟踪:

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] 

出于某种原因,虚拟化堆栈面板正试图清理索引的元素-1(你可以在栈帧中看到这个索引值)。

ObservableCollection的内容的类型没有区别。你得到了与字符串相同的错误......并且只发生在两个元素上。

对我来说,它在VirtualizingStackPanel中看起来像一个bug。您可以通过将虚拟化模式设置为标准而不是回收列表框来解决此问题(如果您不需要虚拟化功能):

<ListBox VirtualizingStackPanel.VirtualizationMode="Standard" 
    ... 
</ListBox> 
+0

感谢您的调试。我结束了另一个解决方案,因为当我将VirtualizationMode设置为标准时,ListBox最终变为空的。 – 2011-05-07 21:59:17

+0

奇怪 - 它对我有用......您可能想在解决方案中使用Words.Insert(索引,数字),而不是Add。 – Damian 2011-05-07 22:07:21

2

作为替代方案,为什么不使用数据绑定,而不是将代码中的itemSource设置为背后?

相关问题