在WPF应用程序中,由LINQ填充ObservableCollection并将其更新为SQL查询。然后,使用此ObservableCollection中的值更新UI对象。
是否有可能在一个单独的线程中执行通过LINQ将此ObservableCollection更新为SQL查询的操作,这是否合理?
如果是,在这种情况下,它将是此ObservableCollection的一个实例吗? (我的意思是,如果从LINQ数据上下文中获取值与提供值以更新UI的方式不同,那么我将无法更新UI)
使用内置的ObservableCollection<T>
类,如果将UI绑定到集合,则无法从单独的线程更改内容,它会抛出NotSupportedException
(但是对集合项的属性进行更改通知的效果很好) 。我写了一个AsyncObservableCollection<T>
class处理这种情况。它通过在UI同步上下文上调用事件处理程序来工作]
。Net 4.5在BindingOperations类中提供了一个解决方案。
您现在可以如下使用BindingOperations.EnableCollectionSynchronization方法:
AsyncObservableCollection<T>
[我只是在开发环境中尝试过,但是当我从后台线程更新集合时,现在一切似乎都可以正常工作。
private readonly object _personCollectionLock;
private ObservableCollection<Person> _personCollection;
public ObservableCollection<Person> PersonCollection
{
get { return _personCollection; }
set
{
_personCollection = value;
BindingOperations.EnableCollectionSynchronization(_personCollection, _personCollectionLock);
}
上对此解决方案有更深入的讨论>
此方法的MSDN条目位于:http://10rem.net/blog/2012/01/16/wpf-45-observable-collection-cross-thread-change-notification
在我们的应用程序中,我们有一个绑定到ObservableCollection的TreeView,我们会定期在后台线程中对其进行更新,以从存储中请求数据。它完美地工作!
试图在这里理解您的问题:
我没有收到相同的public class MTObservableCollection<T> : ObservableCollection<T>
{
public override event NotifyCollectionChangedEventHandler CollectionChanged;
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
var eh = CollectionChanged;
if (eh != null)
{
Dispatcher dispatcher = (from NotifyCollectionChangedEventHandler nh in eh.GetInvocationList()
let dpo = nh.Target as DispatcherObject
where dpo != null
select dpo.Dispatcher).FirstOrDefault();
if (dispatcher != null && dispatcher.CheckAccess() == false)
{
dispatcher.Invoke(DispatcherPriority.DataBind, (Action)(() => OnCollectionChanged(e)));
}
else
{
foreach (NotifyCollectionChangedEventHandler nh in eh.GetInvocationList())
nh.Invoke(this, e);
}
}
}
}
,但是不幸的是,如果我从另一个线程设置了我的System.NotSupportedException
,则我的[[UI没有正确更新]。