EF LoadAsync后刷新视图

时间:2014-07-27 07:07:00

标签: c# wpf entity-framework observablecollection icollectionview

假设要加载大量数据,我希望UI在加载数据时能够响应。目前唯一的工作代码是不断刷新不需要的UI。如何在非UI线程中加载数据并在视图上获得最终更新?

private static object sync_lock = new object();

private void Load()
{
    MyEntities db = new MyEntities();

    TestEntityViewModel testEntityViewModel = (TestEntityViewModel)FindResource("testEntityViewModel");

    testEntityViewModel.Source = db.TestEntities.Local; // Source is ObservableCollection<TestEntity>

    BindingOperations.EnableCollectionSynchronization(testEntityViewModel.Source, sync_lock);

            db.TestEntities.LoadAsync().ContinueWith(new Action<Task>(
                (t) =>
                {
                    this.Dispatcher.Invoke(new Action(() =>
                    {
                        View.MoveCurrentToFirst();

                        CommandManager.InvalidateRequerySuggested();
                    }));
                }));
}

注意:如果我删除了对EnableCollectionSynchronization的调用,则会加载数据,但ICollectionView及其SourceCollection只有1项。

1 个答案:

答案 0 :(得分:1)

你似乎在使用MVVM。这就是我在我的应用程序中的表现。

interface ISomeDataService{
    void GetModelItems(Action<Model[], Exception> callback);
}


class SomeDataServiceImpl:ISomeDataService{
    void GetModelItems(Action<Model[], Exception> callback){
        Task.Factory.StartNew(()=>{
            //get model items from WCF for example than call the callback
            //expected to take a while. 
            //you can also directly access DbContext from here
            //if you like
            callback(res, null);
        });
    }
}

您现在需要在VM中使用此实现。你可以像下面这样做。

class MyDemoVM{
    private Model[] items;
    private readonly ISomeDataService service;
    private readonly IDispatcherService dispService;
    public MyDemoVM(){
        service=new SomeDataServiceImpl();
        dispService=new DispatcherService();
        //i use ctor injection here in order to break the dependency on SomeDataServiceImpl and on DispatcherService.
        //DispatcherService delegates to the App dispatcher in order to run code
        //on the UI thread.
    }
    public Model[] Items{
        get{
            if(items==null)GetItems();
            return items;
        }
        set{
            if(items==value)return;
            items=value;
            NotifyChanged("Items");
        }
    }
    private void GetItems(){
        service.GetModelItems((res,ex)=>{
            //this is on a different thread so you need to synchronize
            dispService.Dispatch(()=>{
                Items=res;
            });
        });
    }
}

此代码使用延迟加载。当UI控件读取Items属性时,将下载数据。在下载所有数据后,此代码将仅刷新一次集合。请注意,此示例适用于.net 4.如果您使用.net 4.5,则可以使用async / await关键字使服务更具可读性。但这个概念是一样的。