VisualCollection抛出了超出范围的异常,与Observable collection绑定。

8

我有一个可观察的集合绑定到了ItemsControl。

当我向集合中添加项目时,我会收到来自Visual集合的索引超出范围的异常。

<ItemsControl x:Name="ReportPages" ItemsSource="{Binding History}" DockPanel.Dock="Top">
    <ItemsControl.Template>
        <ControlTemplate TargetType="ItemsControl">
            <ItemsPresenter HorizontalAlignment="Center"/>
        </ControlTemplate>
    </ItemsControl.Template>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ItemsControl ItemsSource="{Binding ChildWindows}">
                <ItemsControl.Template>
                    <ControlTemplate TargetType="ItemsControl">
                        <Grid Margin="0,10,0,10" >
                            <ItemsPresenter />
                            <Border x:Name="ResizeFrame" BorderThickness="4" BorderBrush="LightBlue"  Visibility="{Binding Active, Converter={StaticResource BooleanToVisibilityConverter}}"/>
                        </Grid>
                    </ControlTemplate>
                </ItemsControl.Template>
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas x:Name="LayoutCanvas" Background="white" ClipToBounds="true"
                    MouseDown="History_MouseLeftButtonDown" PreviewMouseDown="ClosePanels"
                    Width="{Binding PageSizeProp.PageWidth}" Height="{Binding PageSizeProp.PageHeight}"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

内部ChildWindows是我正在添加项目的集合。需要注意的一点是,ChildWindows是一个ReadOnlyObservableCollection,我是通过一个可以访问它所基于的集合的方法来添加的。

我完全不知道为什么会发生这种情况(而且只有有时候会发生)。

编辑: 以下是实际的堆栈跟踪

at System.Windows.Media.VisualCollection.Insert(Int32 index, Visual visual)
   at System.Windows.Controls.Panel.addChildren(GeneratorPosition pos, Int32 itemCount)
   at System.Windows.Controls.Panel.OnItemsChangedInternal(Object sender, ItemsChangedEventArgs args)
   at System.Windows.Controls.Panel.OnItemsChanged(Object sender, ItemsChangedEventArgs args)
   at System.Windows.Controls.ItemContainerGenerator.OnItemAdded(Object item, Int32 index)
   at System.Windows.Controls.ItemContainerGenerator.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
   at System.Windows.Controls.ItemContainerGenerator.System.Windows.IWeakEventListener.ReceiveWeakEvent(Type managerType, Object sender, EventArgs e)
   at System.Windows.WeakEventManager.DeliverEventToList(Object sender, EventArgs args, ListenerList list)
   at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args)
   at System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
   at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args)
   at System.Windows.Controls.ItemCollection.System.Windows.IWeakEventListener.ReceiveWeakEvent(Type managerType, Object sender, EventArgs e)
   at System.Windows.WeakEventManager.DeliverEventToList(Object sender, EventArgs args, ListenerList list)
   at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args)
   at System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
   at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args)
   at System.Windows.Data.ListCollectionView.ProcessCollectionChangedWithAdjustedIndex(NotifyCollectionChangedEventArgs args, Int32 adjustedOldIndex, Int32 adjustedNewIndex)
   at System.Windows.Data.ListCollectionView.ProcessCollectionChanged(NotifyCollectionChangedEventArgs args)
   at System.Windows.Data.CollectionView.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
   at System.Collections.ObjectModel.ReadOnlyObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs args)
   at System.Collections.ObjectModel.ReadOnlyObservableCollection`1.HandleCollectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
   at System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
   at System.Collections.ObjectModel.ObservableCollection`1.InsertItem(Int32 index, T item)
   at System.Collections.ObjectModel.Collection`1.Add(T item)
   at CalManv4UI.DataHistoryReportPageBase.AddNewChart(ChildWindowSaved cws, Boolean activate) in C:\Users\Joel Barsotti\Documents\Visual Studio 2010\Projects\CalMAN V4\CalMANv4-WPF\CalManv4UI\Workflow\DataHistoryReportPageBase.cs:line 72

集合中有多少项? - Robert Levy
我也遇到了同样的问题。如果我找到解决方案,我会在这里发布。 - SergioL
我也遇到了这个问题,在一个静态的CompositeCollection中包含了一个可观察集合和一些静态项。通过将CompositeCollection的x:Shared属性设置为“False”,我能够摆脱错误,但我非常想知道这个问题的真正正确答案是什么。这似乎几乎像是一个bug。 - BTownTKD
2个回答

4

我有同样的问题,根据https://stackoverflow.com/users/249723/vivien-ruiz提供的链接,我的理解是,如果您修改了一个在ItemSource绑定中参与的ObservableCollection,则会“限制”出现问题。 我发现在索引0处插入可以“解决”我的问题,但仍可能崩溃。 由于它不是线程安全的类,因此不应该被修改。 更好的解决方案是对列表副本进行操作,并在完成操作后将该副本分配给绑定集合。举个例子: ObservableCollection<ListViewItem> newList = new ObservableCollection<ListViewItem>(mCurrentList); ... ListViewItem item = new ListViewItem(); item.Content = image; newList.Add(item); ... mPictures = newList;


-1

我曾经遇到过类似的问题,花了我几个月的时间才找到原因,但最终还是找到了 ^^ 请查看此网站,特别是如果您修改了来自另一个线程的列表。您似乎遇到了竞态条件,可能是同样的问题!


2
内联答案。该链接已失效。 - CristianDonosoC
这是文章链接:使用web.archive.org的链接 - Coden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接