2010-11-15 108 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