0

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

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

你似乎在使用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); 
     }); 
    } 
} 

你现在需要在你的虚拟机中使用这个实现。你可以像下面这样做。

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关键字来提高服务的可读性。但这个概念是一样的。