更新ObservableCollection会导致“参数不正确”异常

时间:2011-05-07 16:41:26

标签: silverlight exception xaml windows-phone-7 observablecollection

我有一个奇怪的问题,我不明白。这是在Silverlight / WP7中。

我正在用项目填充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,它们显示在ListBox中。

第二次运行时,所有代码都被执行,但随后会抛出一条带有“参数不正确”消息的未处理异常。

奇怪的是,如果我在构造函数中删除了我的行,那是我设置ItemsSource的行,则不会抛出错误。可观察的集合会按原样更新。

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

有人可以解释原因吗? (或建议解决方法?)

我的解决方案; 我从

改变了我的代码隐藏
if (index > -1)
    Words[index] = number;

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

这使问题消失了。

2 个答案:

答案 0 :(得分:3)

如果启用CLR Exceptons在抛出时中断(在Debug | Exceptions下),您将看到此堆栈跟踪:

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上将VirtualizationMode设置为Standard而不是Recycling来解决它(如果您不需要虚拟化功能):

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

答案 1 :(得分:2)

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