gpt4 book ai didi

c# - 升级到 .NET 4.5 : An ItemsControl is inconsistent with its items source

转载 作者:IT王子 更新时间:2023-10-29 04:18:11 26 4
gpt4 key购买 nike

我正在构建一个应用程序,它使用许多 ItemControls(数据网格和 ListView )。为了从后台线程轻松更新这些列表,我使用了 ObservableCollections 的这个扩展,它运行良好:

http://geekswithblogs.net/NewThingsILearned/archive/2008/01/16/have-worker-thread-update-observablecollection-that-is-bound-to-a.aspx

今天我安装了 VS12(它又安装了 .NET 4.5),因为我想使用一个为 .NET 4.5 编写的组件。在将我的项目升级到 .NET 4.5(从 4.0)之前,我的数据网格在从工作线程更新时开始抛出 InvalidOperationException。异常信息:

This exception was thrown because the generator for control 'System.Windows.Controls.DataGrid Items.Count:5' with name '(unnamed)' has received sequence of CollectionChanged events that do not agree with the current state of the Items collection. The following differences were detected: Accumulated count 4 is different from actual count 5. [Accumulated count is (Count at last Reset + #Adds - #Removes since last Reset).]

重现代码:

XAML:

<Window x:Class="Test1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid ItemsSource="{Binding Items, Mode=OneTime}" PresentationTraceSources.TraceLevel="High"/>
</Grid>
</Window>

代码:

public partial class MainWindow : Window
{
public ExtendedObservableCollection<int> Items { get; private set; }

public MainWindow()
{
InitializeComponent();
Items = new ExtendedObservableCollection<int>();
DataContext = this;
Loaded += MainWindow_Loaded;
}

void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() =>
{
foreach (var item in Enumerable.Range(1, 500))
{
Items.Add(item);
}
});
}
}

最佳答案

WPF 4.5 提供了一些新功能来访问非 UI 线程上的集合。

It WPF enables you to access and modify data collections on threads other than the one that created the collection. This enables you to use a background thread to receive data from an external source, such as a database, and display the data on the UI thread. By using another thread to modify the collection, your user interface remains responsive to user interaction.

这可以通过使用静态方法来完成 EnableCollectionSynchronizationBindingOperations 类上。

If you have a lot of data to collect or modify, you might want to use a background thread to collect and modify the data so that the user interface will remain reactive to input. To enable multiple threads to access a collection, call the EnableCollectionSynchronization method. When you call this overload of the EnableCollectionSynchronization(IEnumerable, Object) method, the system locks the collection when you access it. To specify a callback to lock the collection yourself, call the EnableCollectionSynchronization(IEnumerable, Object, CollectionSynchronizationCallback) overload.

用法如下。创建一个对象,用作集契约(Contract)步的锁。然后调用 BindingsOperations 的 EnableCollectionSynchronization 方法,将要同步的集合和用于锁定的对象传递给它。

我已经更新了您的代码并添加了详细信息。此外,我将集合更改为普通的 ObservableCollection 以避免冲突。

public partial class MainWindow : Window{
public ObservableCollection<int> Items { get; private set; }

//lock object for synchronization;
private static object _syncLock = new object();

public MainWindow()
{
InitializeComponent();
Items = new ObservableCollection<int>();

//Enable the cross acces to this collection elsewhere
BindingOperations.EnableCollectionSynchronization(Items, _syncLock);

DataContext = this;
Loaded += MainWindow_Loaded;
}

void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() =>
{
foreach (var item in Enumerable.Range(1, 500))
{
lock(_syncLock) {
Items.Add(item);
}
}
});
}
}

另请参阅:http://10rem.net/blog/2012/01/20/wpf-45-cross-thread-collection-synchronization-redux

关于c# - 升级到 .NET 4.5 : An ItemsControl is inconsistent with its items source,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14336750/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com