web-dev-qa-db-fra.com

Un ItemsControl est incompatible avec la source de ses éléments - WPF Listbox

J'ai une fenêtre WPF contenant un contrôle ListBox qui est rempli lorsqu'une méthode de clic de bouton est exécutée.

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();
    }

Jusqu'à ce stade, tout fonctionne comme prévu et la zone de liste contient plusieurs lignes d'éléments, en fonction du nombre d'éléments figurant dans la liste ThirdPartyListBox.DataContext = RegScan_ThirdParty.comparisonListWithState;. Toutefois, si j'interagis avec les éléments de la zone de liste, une exception InvalidOperationException est émise avec une exception interne "Un ItemsControl n'est pas cohérent avec sa source d'éléments".

Est-ce que quelqu'un peut m'aider à comprendre ce qui se passe?

17
user3342256

Ces exceptions sont levées lorsque la source d'un élément a été modifiée à partir d'un autre thread et que ListBox ne reçoit pas de notification (événement CollectionChanged) indiquant que ItemsSource est en cours de modification. Ainsi, quand il commencera à faire un travail (comme la mise à jour de la disposition), il verra que Items n'est pas égal à ItemsSource et lève une exception.

Depuis .NET 4.5, WPF offre un moyen d'activer la synchronisation avec une collection qui change à partir de différents threads. Essayez d’utiliser la méthode EnableCollectionSynchronization sur votre ItemsSource.

23
neptunao

Vous pouvez simplement appeler la méthode Refresh () sur votre contrôle où les ressources de liaison ont été modifiées:

myListBox.Items.Refresh();
11
Dragon

J'ai rencontré le même message d'erreur parce que je nettoyais puis mettais à jour une liste avec une liaison d'interface utilisateur plusieurs fois (boucle) d'une seule méthode.

La solution consistait à créer une liste temporaire et à attribuer la nouvelle liste une seule fois.

Pas directement votre problème mais la même erreur alors j'ai pensé que je le mentionnerais ici ...

0
CodingYourLife