ItemsControl 与其项目源不一致 - WPF 列表框

问题描述 投票:0回答:6

我有一个 WPF 窗口,其中包含一个 ListBox 控件,当执行按钮单击方法时会填充该控件。

XAML:

<ListBox Name="ThirdPartyListBox" ItemsSource="{Binding}" Margin="0,70,0,0">                      
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <Image Source="C:\Users\Test\Desktop\Project\ACME-WPF\ACME-WPF\window-new-3.ico" Margin="5" Width="50"/>
                                <Button Name="ThirdPartyInstallButton" Content="Install" Click="InstallThirdPartyUpdatesButton_Click" Margin="5,5,0,0" Height="25"></Button>
                                <Button Name="ThirdPartyPostoneButton" Content="Postpone" Click ="PostponeThirdPartyUpdatesButton_Click" Margin="5,5,0,0" Height="25"></Button>
                                <TextBlock FontWeight="Bold" Text="{Binding Item2.Name}" Margin="12,25,0,0"/>
                                <TextBlock FontWeight="Bold" Text="{Binding Item2.RequiredVersion}" Margin="3,25,0,0"/>
                                <TextBlock Text="{Binding Item2.CustomUIMessage}" Margin="10,25,0,0" TextWrapping="Wrap" Foreground="Red"/>
                                <TextBlock Text="You have used " Margin="3,25,0,0"/>
                                <TextBlock Text="{Binding Item3.UsedDeferrals}" Margin="3,25,0,0"/>
                                <TextBlock Text=" of " Margin="3,25,0,0"/>
                                <TextBlock Text="{Binding Item2.MaxDefferals}" Margin="3,25,0,0"/>
                                <TextBlock Text=" deferrals for this update." Margin="3,25,0,0"/>
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>

C#:

 private void CheckforThirdPartyUpdatesButton_Click(object sender, RoutedEventArgs e)
    {
        CheckforThirdPartyUpdatesButton.IsEnabled = false;

        worker = new BackgroundWorker();
        worker.WorkerReportsProgress = true;
        worker.WorkerSupportsCancellation = true;

        worker.DoWork += delegate(object s, DoWorkEventArgs args)
        {
            MainEntry.checkFor3PUpdates();
        };

        worker.ProgressChanged += delegate(object s, ProgressChangedEventArgs args)
        {

        };

        worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
        {

            ThirdPartyListBox.DataContext = RegScan_ThirdParty.comparisonListWithState;
            CheckforThirdPartyUpdatesButton.IsEnabled = true;
        };

        worker.RunWorkerAsync();
    }

到目前为止,一切都按预期运行,并且列表框中填充了多行项目,具体取决于列表中有多少项目

ThirdPartyListBox.DataContext = RegScan_ThirdParty.comparisonListWithState;
。但是,如果我与列表框项进行交互,则会引发 InvalidOperationException 并带有内部异常“ItemsControl 与其项源不一致。”

有人可以帮助我了解发生了什么事吗?

c# wpf xaml listbox
6个回答
32
投票

当项目的源已从另一个线程更改并且

ListBox
未收到有关
CollectionChanged
更改的通知(
ItemsSource
事件)时,会引发此类异常;所以当它开始做一些工作(比如更新布局)时,它会发现
Items
不等于
ItemsSource
并抛出异常。

自 .NET 4.5 起,WPF 提供了一种方法来启用与不同线程更改的集合的同步。尝试在您的 EnableCollectionSynchronization

 上使用 
ItemsSource
 方法。请参阅类似问题的答案

中的示例用法

30
投票

您可以在更改绑定资源的控件上简单地调用 Refresh() 方法:

myListBox.Items.Refresh();

8
投票

我也有同样的错误。这是由于编辑列表中用作 ItemsSource 的对象引起的。

我的解决方案是用 ObservableCollection 替换 List。 根据 .NET 文档,ObservableCollection:

“表示动态数据集合,当添加、删除项目或刷新整个列表时提供通知。”


1
投票

我遇到了完全相同的错误消息,因为我在一个方法中多次(循环)清除并更新具有 UI 绑定的列表。

解决方案是创建一个临时列表并仅分配新列表一次。

不是直接你的问题,而是同样的错误,所以我想我会在这里提到它......


0
投票

我遇到了同样的错误“ItemsControl 与其项目源不一致”,但我是从 UI 线程执行所有操作的。我正在使用一个实现

ICollectionView
作为
ItemsSource
的类。我自己开发了这个视图。

问题在于,在引发

ICollectionView.GetEnumerator()
事件之前,视图并未使从
CollectionChanged
返回的枚举器无效。
ItemsSource
在内部缓存枚举器以及使用它们获得的任何结果。如果枚举器没有失效,它会很乐意重用它们和派生值,包括项目计数。

要使枚举器无效,请从其

InvalidOperationException
属性以及
Current
MoveNext()
方法中抛出
Reset()
。然后,
ItemsControl
将请求一个新的枚举器并重新创建缓存的数据。如果您的枚举器实现了
IDisposable
,它也会首先调用
Dispose()


-1
投票

如果您的集合实现了 INotifyCollectionChanged,您还可以发送 NotifyCollectionChangedAction.Reset 消息,基本上是说“我把一切都搞砸了,让我们重新开始吧。”

© www.soinside.com 2019 - 2024. All rights reserved.