ItemsControl与其项目源 - WPF Listbox不一致

时间:2014-03-20 05:56:57

标签: c# wpf xaml listbox

我有一个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,内部异常&#34; ItemsControl与其项源不一致。&#34;

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

5 个答案:

答案 0 :(得分:23)

当项目的来源从另一个线程发生变化并且ListBox未收到有关CollectionChanged被更改的通知(ItemsSource事件)时,会抛出此类异常;所以当它开始做一些工作(比如更新布局)时,它会看到Items不等于ItemsSource并抛出异常。

从.NET 4.5开始,WPF提供了一种与从不同线程更改的集合启用同步的方法。尝试在ItemsSource上使用EnableCollectionSynchronization方法。

答案 1 :(得分:13)

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

myListBox.Items.Refresh();

答案 2 :(得分:2)

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

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

“表示一个动态数据收集,当添加,删除或刷新整个列表时,将提供通知。”

答案 3 :(得分:1)

我遇到了非常相同的错误消息,因为我正在清除,然后在单个方法中使用UI绑定多次(循环)更新了一个列表。

解决方案是创建一个临时列表,然后只分配一次新列表。

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

答案 4 :(得分:-1)

如果您的集合实现了INotifyCollectionChanged,则还可以发送NotifyCollectionChangedAction.Reset消息,基本上说:“我搞砸了所有内容,让我们重新开始。”