使用MVVM中的后台工作程序更新ObservableCollection [英] Update an ObservableCollection with a background worker in MVVM

查看:317
本文介绍了使用MVVM中的后台工作程序更新ObservableCollection的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,我最近实现了一个后台工作器来执行数据的保存和加载.

Ok, I recently implemented a background worker to perform saving and loading of data.

但是,事实证明很难在保存命令上使用它.

However, getting this to work on a save command has proved difficult.

基本上,我的save命令会生成一个事件,该事件通知集合视图模型,已添加项目,并且应将项目添加到其自己的ObservableCollection中.

Basically, my save command generates an event, that notifies a collection view model, that an Item has been added and that the item should be added to its own ObservableCollection.

在这一点上,我得到一个通常的异常,说我无法在其他线程上更新ICollection.我尝试创建一个调用Dispatcher.Invoke的新列表类型,但这仍然会生成相同的异常.

At this point, I get the usual exception saying I can NOT update an ICollection on a different thread. I have tried creating a new list type that calls Dispatcher.Invoke, however this still generates the same exception.

我想知道是否有人对如何最好地解决这个问题有任何建议?

I was wondering whether anyone else has any suggestions on how best to tackle this?

所以目前我有一个继承自ObservableCollection的类:

So currently I have a class that Inherits from ObservableCollection:

public class ThreadSafeObservableCollection<T> : ObservableCollection<T>
{
    public ThreadSafeObservableCollection(List<T> collection)
        : base(collection)
    {
        dispatcher = Dispatcher.CurrentDispatcher;
        rwLock = new ReaderWriterLock();
    }

    protected override void InsertItem(int index, T item)
    {
        if (dispatcher.CheckAccess())
        {
            if (index > this.Count)
                return;
            LockCookie c = rwLock.UpgradeToWriterLock(-1);
            base.InsertItem(index, item);
            rwLock.DowngradeFromWriterLock(ref c);
        }
        else
        {
            object[] obj = new object[] { index, item };
            dispatcher.Invoke(
                DispatcherPriority.Send, 
                (SendOrPostCallback)delegate { InsertItemImpl(obj); }, 
                obj);
        }
    }

然后我有一个视图模型类,该类具有一个执行保存的后台工作程序.

I then have a view model class that has a background worker which carries out the save.

保存完成后,将向另一个视图模型触发一个事件以更新其列表.

Once the save is complete, an event is fired to another view model to update its list.

    protected override void OnObjectAddedToRepository(object sender, ObjectEventArgs<cdAdministrators> e)
    {
        Dispatcher x = Dispatcher.CurrentDispatcher;
        var viewModel = new AdministratorViewModel(e.EventObject, DataAccess);
        viewModel.RecentlyAdded = true;
        viewModel.ItemSelected += this.OnItemSelected;
        this.AllViewModels.Add(viewModel);
        RecentlyAddedViewModel = viewModel;

        OnPropertyChanged(null);
    }

两个列表都是由单独的后台工作程序线程创建的.

Both lists are created by a separate background worker thread.

推荐答案

在获得将项目添加到可观察集合(大概在视图模型中)的代码的地方,将Add调用包装在Dispatcher.BeginInvoke中打电话.

Where you've got code which adds the item to the observable collection (presumably in the view model), wrap that Add call in a Dispatcher.BeginInvoke call.

诚然,这意味着视图模型需要了解调度程序,然后很难进行测试...幸运的是,引入自己的IDispatcher接口并以常规方式使用依赖注入并不是很困难.

Admittedly that means the view model needs to know about the dispatcher, which then becomes awkward to test... fortunately it's not too hard to introduce your own IDispatcher interface and use dependency injection in the normal way.

这篇关于使用MVVM中的后台工作程序更新ObservableCollection的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆