ItemsControl与它的项目来源不一致。\ n有关更多信息,请参见内部异常

此消息我处于中断模式:

Inner Exception
Exception: Information for developers (use Text Visualizer to read this):
This exception was thrown because the generator for control 'System.Windows.Controls.ListBox Items.Count:4' with name '(unnamed)' has received sequence of CollectionChanged events that do not agree with the current state of the Items collection.  The following differences were detected:
  accumulated count 3 is different from actual count 4.  [accumulated count is (Count at last Reset + #Adds - #Removes since last Reset).]
  At index 1:  Generator's item 'Data.DisplayNews' is different from actual item 'Data.DisplayNews'.

One or more of the following sources may have raised the wrong events:
     System.Windows.Controls.ItemContainerGenerator
      System.Windows.Controls.ItemCollection
       System.Windows.Data.ListCollectionView
  *     Data.AsyncObsetion`1[[Data.DisplayNews,Data,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null]]
(The starred sources are considered more likely to be the cause of the problem.)

The most common causes are (a) changing the collection or its Count without raising a corresponding event,and (b) raising an event with an incorrect index or item parameter.

The exception's stack trace describes how the inconsistencies were detected,not how they occurred.  To get a more timely exception,set the attached property 'PresentationTraceSources.TraceLevel' on the generator to value 'High' and rerun the scenario.  One way to do this is to run a command similar to the following:\n   System.Diagnostics.PresentationTraceSources.SetTraceLevel(myItemsControl.ItemContainerGenerator,System.Diagnostics.PresentationTraceLevel.High)
from the Immediate window.  This causes the detection logic to run after every CollectionChanged event,so it will slow down the application.

在代码中,我以这种方式在NewsCollection中添加了服务器发送的新闻:

void AddNews(byte[] array)
{
    for (int i = 0; i < array.Length; i += newsSize)
    {
        var n = PacMan<Data.News>.Unpack(array.Skip(i).Take(newsSize).ToArray());
        NewsCollection.Insert(0,new DisplayNews()
        {
            Time = n.Time,ItemCode = n.ItemCode,ItemName = Items.First(x => x.Id == n.ItemCode).Name,Feed = n.Feed
        });
    }
}

NewsCollection是通过以下方式实现的ObservableCollection

public class AsyncObsetion<T> : ObservableCollection<T>
{
    private SynchronizationContext context = SynchronizationContext.Current;
    public AsyncObsetion() { }
    public AsyncObsetion(IEnumerable<T> list) : base(list) { }

    void RaiseCollectionChanged(object param) => base.OnCollectionChanged((NotifyCollectionChangedEventArgs)param);
    void RaisePropertyChanged(object param) => base.OnPropertyChanged((PropertyChangedEventArgs)param);

    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if (SynchronizationContext.Current == context) RaiseCollectionChanged(e);
        else context.Send(RaiseCollectionChanged,e);
    }

    protected override void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (SynchronizationContext.Current == context) RaisePropertyChanged(e);
        else context.Send(RaisePropertyChanged,e);
    }      
}

DisplayNews已为其所有属性实现了INotifyPropertyChanged。在xaml中,我拥有这些:

<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
    ItemsSource="{Binding Source={x:Static VM:ClientCode.NewsCollection}}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid Margin="0 0 0 12" x:Name="newsGrid">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <TextBlock Text="{Binding Time}" FontWeight="Bold" Margin="0 0 20 0"/>
                <Grid Grid.Column="1">
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>
                    <TextBlock Text="{Binding ItemName}" FontWeight="Bold"/>
                    <TextBlock Grid.Row="1" Text="{Binding Feed}" TextWrapping="Wrap"/>
                </Grid>
            </Grid>

            <DataTemplate.Resources>
                <Storyboard x:Key="Appear">
                    <DoubleAnimationUsingKeyFrames 
                            Storyboard.TargetName="newsGrid"
                            Storyboard.TargetProperty="Opacity">
                        <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                        <EasingDoubleKeyFrame KeyTime="0:0:0.7" Value="1"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </DataTemplate.Resources>

            <DataTemplate.Triggers>
                <EventTrigger RoutedEvent="Loaded">
                    <BeginStoryboard Storyboard="{StaticResource Appear}"/>
                </EventTrigger>
            </DataTemplate.Triggers>

        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

当服务器一次发送多个新闻时,会发生此错误。如果服务器仅发送一个新闻,则不会出现此错误!如何解决这个问题?


编辑

如果我将ListBox替换为ListView,则会遇到相同的错误!唯一没有问题的方法是当我在ItemsControl中使用ListBox而不是ListViewItemsControl但没有SelectedItem的功能时。


编辑

解决方案似乎是在App.Current.Dispatcher.Invoke函数中添加AddNews,如下所示:

void AddNews(byte[] array)
{
    for (int i = 0; i < array.Length; i += newsSize)
    {
        var n = PacMan<Data.News>.Unpack(array.Skip(i).Take(newsSize).ToArray());
        App.Current.Dispatcher.Invoke(() =>
        {
            NewsCollection.Insert(0,new DisplayNews()
            {
                Time = n.Time,Feed = n.Feed
            });
        });
    }
}

contextpublic class AsyncObsetion<T> : ObservableCollection<T>中正在做什么?我已经添加了AsyncObsetion<T>来避免在用户界面中使用的列表以及在其他确实能够完成工作的所有其他情况下始终避免使用App.Current.Dispatcher.Invoke


编辑

现在的问题是,为什么在没有AsyncObsetion<T>App.Current.Dispatcher.Invoke的情况下ItemsControl可以工作,但是在这种特殊情况下却不能与ListBoxListView一起工作? Framework是否有问题,或者我在代码中缺少某些内容?

我还有一个名为AsyncObsetion<T>的{​​{1}}挂接到了另一个ExecutedOrders上,它也可以正常工作。 ListViewExecutedOrder之间的唯一区别是,如果News服务器可以一次发送一个或多个,则服务器一次只能发送一个ExecutedOrder


编辑

根据this,在两个构造函数中调用News是另一种解决方案。要使用它,我必须在我的WPF项目的所有3个(客户端,特殊客户端和服务器)中复制BindingOperations.EnableCollectionSynchronization(this,_lock);的副本!我将AsyncObsetion<T>放在一个单独的类库中,所有这3个项目都对此进行了引用。

asas8520 回答:ItemsControl与它的项目来源不一致。\ n有关更多信息,请参见内部异常

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/3102137.html

大家都在问