Элемент ItemsControl несовместим с источником элементов - WPF 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>
С#:
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 несовместим со своим источником элементов".
Может кто-нибудь помочь мне понять, что происходит?
Ответы
Ответ 1
Такие исключения выбрасываются, когда источник источника был изменен из другого потока, а ListBox
не получает уведомление (CollectionChanged
event) о ItemsSource
, которое изменяется; поэтому, когда он начинает выполнять некоторую работу (например, обновлять макет), он увидит, что Items
не равно ItemsSource
и генерирует исключение.
Начиная с .NET 4.5, WPF предоставляет возможность включить синхронизацию с коллекцией, которая изменяется из разных потоков. Попробуйте использовать EnableCollectionSynchronization
метод ItemsSource
.
Ответ 2
Вы можете просто вызвать метод Refresh() для вашего элемента управления, где были изменены ресурсы привязки:
myListBox.Items.Refresh();
Ответ 3
Я столкнулся с тем же сообщением об ошибке, потому что я очищал, а затем обновлял список с привязкой пользовательского интерфейса несколько раз в одном методе.
Решением было создать временный список и назначить новый список только один раз.