2010-11-15 2 views
0

Je souhaite mettre à jour mon interface utilisateur. Dois-je utiliser BackgroundWorker? Est-ce que je mets le BackgroundWorker dans MainWindowViewModel et instancie les dépôts de nouveau, ou est-ce que je le mets dans le OrdersQueueViewModel et fais quelque chose avec les propriétés?Les collections de mises à jour de MVVM WPF pour mettre à jour l'interface utilisateur

L'interface utilisateur affiche simplement le contenu des listes créées par LINQ. Les listes sont ObservableCollection et sont les propriétés de OrdersQueueViewModel. J'ai un ViewModel MainWindowViewModel qui crée une collection ViewModels, de sorte que je peux lier à cette collection à partir de MainWindow.xaml (vue).

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> 

Exemple d'une propriété dans le OrderQueueViewModel qui utilise un référentiel:

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

J'ai LinesToPick lié dans le OrdersQueueView, et que la base de données met à jour les listes devrait c changer dans l'interface utilisateur. J'ai passé un peu de temps à lire sur BackgroundWorker, mais je ne sais pas trop quoi faire pour mettre à jour les listes. J'espère parce qu'ils sont ObservableCollections je peux juste les «actualiser» et ils emploieront INotifyPropertyChanged et mettront à jour l'interface utilisateur automatiquement. Très nouveau à tout cela, en essayant de comprendre, merci d'avance pour toute aide.

EDIT: En utilisant la suggestion de James, je me suis retrouvé avec ceci dans mon OrdersQueueViewModel. Cependant, je reçois l'erreur "Ce type de CollectionView ne prend pas en charge les modifications apportées à sa SourceCollection à partir d'un thread différent du thread Dispatcher", lorsque le code arrive à .Clear() sur les 2 listes, ce qui est ce que je pensais expéditeur a été utilisé pour. Aucune suggestion?

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

Répondre

0

Vous pouvez le faire de toute façon - dans le modèle MainWindowViewModel ou l'un des modèles de vue enfant. Je choisirais sur la base de ce qui produit un couplage inférieur et une cohésion plus élevée entre les composants. (Couplage inférieur - moins de dépendances.) Cohésion plus élevée - les éléments vont ensemble et logiquement ensemble.)

Et BackgroundWorker est une technique raisonnable. Rappelez-vous juste d'envoyer au fil de l'interface utilisateur pour mettre à jour la collection. Quant à votre code ObservableCollection ... Cela demande du travail. Ne réinstallez pas ObservableCollection. Faites quelque chose comme ceci:

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

En gardant la même ObservableCollection qui était lié aux données, votre interface utilisateur choisira automatiquement des modifications à la collection. Si vous remplacez la collection, vous perdez la liaison et votre interface utilisateur ne se met pas à jour tant que vous ne l'avez pas averti que la propriété contenant la collection a été modifiée. Beaucoup plus facile de garder la même collection.

+0

Ma question originale a été répondue, je ne voulais pas vraiment commencer un nouveau fil, j'espère que vous savez peut-être être en mesure de me diriger dans la bonne direction sur cette nouvelle partie. – LobalOrning

+0

Vous avez votre code Dispatcher à l'envers. Vous voulez appeler le répartiteur à l'intérieur de BackgroundWorker, et non l'inverse. BTW - Mon code Refresh() est un peu naïf. Vous devriez vraiment aller chercher la liste des nouveaux éléments sur le thread d'arrière-plan et les passer dans Refresh (newItems) plutôt que d'appeler le repo depuis Refresh. –

Questions connexes