WPF MVVM更新集合以便UI更新

时间:2010-11-15 15:59:12

标签: wpf mvvm backgroundworker observablecollection

我想更新我的用户界面。我应该使用BackgroundWorker吗?我是否将BackgroundWorker放在MainWindowViewModel中并再次实例化存储库,还是将它放在OrdersQueueViewModel中并对属性执行某些操作?

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:

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

OrderQueueViewModel中使用存储库的属性示例:

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

所以我在OrdersQueueView中绑定了LinesToPick,并且随着数据库更新,列表应该在UI中更改。我花了一些时间阅读有关BackgroundWorker的内容,但我不太清楚如何更新列表。我希望因为它们是ObservableCollections我可以“刷新”它们并且它们将使用INotifyPropertyChanged并自动更新UI。对这一切都很陌生,试着先了解它,先谢谢你的帮助。

编辑:使用James的建议我最终得到了这个在我的OrdersQueueViewModel中。但是,当代码到达2个列表上的.Clear()时,我收到错误“这种类型的CollectionView不支持从与Dispatcher线程不同的线程更改其SourceCollection”是我认为调度员的用途。有什么建议吗?

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);

1 个答案:

答案 0 :(得分: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将自动获取对集合的更改。如果替换集合,则会丢失对其的绑定,并且在通知包含集合的属性发生更改之前,UI将不会更新。更容易保持相同的集合。