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關鍵字來提高服務的可讀性。但這個概念是一樣的。