更新 ObservableCollection 会导致“参数不正确”例外
我有一个奇怪的问题我不明白。这是在 Silverlight/WP7 中。
我正在用项目填充 ObservableCollection,稍后我想更新每个项目。
我已经设法删除代码以重现该错误。我的 XAML 只是一个列表框和一个按钮。
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);
}
使得问题消失了。
I've got a weird issue I don't understand. This is in Silverlight/WP7.
I'm filling an ObservableCollection with items, and later I want to update each of the items.
I've managed to strip down 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);
}
}
The first time I run the code it fills the ObservableCollection with the numbers 1, 2 and 3, and they are displayed in the ListBox.
The second time it is run all the code is executed, but then an unhandled exception with the message "The parameter is incorrect" is thrown.
The weird thing is that if I remove my line in the constructor, the one where I set up the ItemsSource, the error isn't thrown. The observable collection is updated as it should.
Also, if I comment out the "Words[index] = number" line it also works. So for some reason, when my ObservableCollection is set as the datasource to a ListBox I can't replace the item.
Can someone explain why? (Or suggest a workaround?)
My solution;
I changed my codebehind from
if (index > -1)
Words[index] = number;
to
if (index > -1)
{
Words.RemoveAt(index);
Words.Add(number);
}
That made the problem go away.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果启用 CLR 异常在抛出时中断(在“调试”|“异常”下),您将看到以下堆栈跟踪:
出于某种原因,虚拟化堆栈面板正在尝试清理索引 -1 处的元素(您可以在堆栈帧)。
ObservableCollection 内容的类型没有区别。对于字符串,您会遇到同样的错误...并且只有两个元素就会发生这种情况。
对我来说,它看起来像是 VirtualizingStackPanel 中的一个 bug。您可以通过将 VirtualizationMode 设置为 Standard 而不是 ListBox 上的 Recycling 来解决此问题(如果您不需要虚拟化功能):
If you enable CLR Exceptons to break when thrown (under Debug|Exceptions) you'll see this stack trace:
For some reason the virtualizing stack panel is trying to clean up the element at index -1 (you can see this value for index in the stack frame).
The type of the ObservableCollection's contents makes no difference. You get the same error with strings ... and it happens with just two elements.
To me it looks like a bug in the VirtualizingStackPanel. You can work around it (if you don't need the virtualizing functionality) by setting the VirtualizationMode to Standard instead of Recycling on the ListBox:
作为替代方案,为什么不使用数据绑定,而不是从代码后面设置 itemSource?
As an alternative, why not use databinding, rather than setting the itemSource from code behind?