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?
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
.
Vous pouvez simplement appeler la méthode Refresh () sur votre contrôle où les ressources de liaison ont été modifiées:
myListBox.Items.Refresh();
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 ...