2010-11-15 70 views
0

我想更新我的UI。我應該使用BackgroundWorker嗎?我是否將BackgroundWorker放在MainWindowViewModel中,並再次實例化存儲庫,或者將它放入OrdersQueueViewModel中並使用屬性進行操作?WPF MVVM更新集合,以便UI更新

UI僅顯示LINQ創建的列表的內容。列表是ObservableCollection,並且是OrdersQueueViewModel的屬性。我有一個ViewModel MainWindowViewModel創建一個集合ViewModels,以便我可以從MainWindow.xaml(視圖)綁定到該集合。

MainWindowViewModel.cs:

public MainWindowViewModel() 
{ 
    _printQueueRepos = new OrdersPrintQueueRepository(); 
    _holdQueueRepos = new OrdersHoldQueueRepository();    
    _linesToPickRepos = new LinesToPickRepository(); 
    _linesPerHourRepos = new LinesPerHourRepository(); 

    //create an instance of viewmodel and add it to the collection    
    OrdersQueueViewModel viewModel = new OrdersQueueViewModel(_printQueueRepos, _holdQueueRepos, _linesToPickRepos, _linesPerHourRepos); 
    this.ViewModels.Add(viewModel);    
} 

MainWindow.xaml:在OrderQueueViewModel屬性的

<Window.Resources> 
    <DataTemplate DataType="{x:Type vm:OrdersQueueViewModel}"> 
     <vw:OrdersQueueView></vw:OrdersQueueView> 
    </DataTemplate> 
</Window.Resources> 

的例子,使用存儲庫:

public ObservableCollection<LinesToPick> LinesToPick 
{ 
    get 
    { 
     return new ObservableCollection<LinesToPick>(_linesToPickRepos.GetLinesToPick()); 
    } 
} 

所以我有LinesToPick綁定在OrdersQueueView中,並且數據庫應該更新列表c在用戶界面中更改。我花了一些時間閱讀關於BackgroundWorker的內容,但我不太確定如何更新列表。我希望因爲他們是ObservableCollections我可以「刷新」他們,他們將使用INotifyPropertyChanged並自動更新用戶界面。所有這些都非常新穎,試圖讓我的頭腦,預先感謝任何幫助。

編輯:使用詹姆斯的建議我已經結束了這個在我的OrdersQueueViewModel。但是,我收到錯誤「這種類型的CollectionView不支持從與分派器線程不同的線程對其SourceCollection的更改」,當代碼到達2列表上的.Clear()時,這是我認爲的調度員被用於。有什麼建議麼?

Action workAction = delegate 
{ 
    _worker = new BackgroundWorker(); 
    _worker.DoWork += delegate 
    { 
     LinesThroughput.Clear(); 
     LinesToPick.Clear(); 

     //refresh LinesToPick 
     foreach (var item in _linesToPickRepos.GetLinesToPick()) 
     { 
      LinesToPick.Add(item); 
     } 

     //refresh LinesThroughput 
     List<LinesThroughput> Lines = new List<LinesThroughput> (_linesPerHourRepos.GetLinesThroughput()); 

     foreach (var item in GetLinesThroughput(Lines)) 
     { 
      LinesThroughput.Add(item); 
     } 
    }; 
    _worker.RunWorkerAsync(); 
}; 
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Normal, workAction); 

回答

0

您可以在MainWindowViewModel或其中一個子視圖模型中執行此操作。我會根據哪種方式產生更低的耦合度和更高的組件間的內聚力來選擇。 (更低的耦合度 - 更少的依賴關係,更高的內聚力 - 事物聚在一起,邏輯上屬於一起)。

而BackgroundWorker是一種合理的技術。只要記得分發到UI線程來更新集合。至於你的ObservableCollection代碼...這需要一些工作。不要重新實例化ObservableCollection。做這樣的事情:

public ObservableCollection<LinesToPick> LinesToPick { get; private set; } // Don't forget to nstantiate in ctor 

public void Refresh() 
{ 
    LinesToPick.Clear(); 
    foreach(var item in _linesToPickRepos.GetLinesToPick()) 
    { 
     LinesToPick.Add(item); 
    } 
} 

通過保持相同的ObservableCollection,這是數據綁定的,你的用戶界面將自動拾取更改集合。如果替換集合,則會失去對該集合的綁定,並且只有在通知它包含該集合的屬性發生更改之後,您的UI纔會更新。更容易保持相同的集合。

+0

我原來的問題得到了回答,並不真正想開始一個新的線程,希望你可能知道能夠指出我在這個新部分的正確方向。 – LobalOrning 2010-11-15 18:45:04

+0

你已經完成了你的Dispatcher代碼。您想從BackgroundWorker內調用調度程序,而不是相反。 BTW - 我的刷新()代碼有點幼稚。您應該在後臺線程中獲取新項目列表,並將其傳遞到Refresh(newItems),而不是從Refresh中調用回購。 – 2010-11-15 19:19:11