2010-10-13 9 views
1

J'ai une NavigationWindow qui implémente une fonctionnalité d'assistant, et un ensemble d'objets Page qui représentent les étapes.multithread view models

Chaque page utilise un modèle de vue distinct.

Certains de ces modèles de vue génèrent des threads de travail à partir de leurs constructeurs. Je termine ces threads lorsque les modèles de vue sont éliminés (ils implémentent IDisposable). En outre, j'affecte ces modèles de vue au DataContext des Pages dans les constructeurs de Pages, et je rejette le DataContext sur l'événement Unloaded. Je fais cela parce que j'ai besoin d'arrêter les threads de travail. Tout cela fonctionne très bien tant que je ne veux pas retourner dans l'assistant. mais si je le fais, la page, puisqu'elle a déjà été déchargée, n'a plus de DataContext et ne montre plus rien. Donc, pour corriger cela, je n'ai pas besoin de disposer du DataContext sur Unloaded, et de donner au modèle de vue l'ordre de démarrer/arrêter son (s) thread (s) quand sa propre fenêtre est chargée/déchargée. Je suppose que j'ai besoin d'introduire quelques méthodes (par exemple, Start() et Stop()) sur le modèle de vue qui ferait cela. et appelez ces méthodes à partir des gestionnaires Initialized et Unloaded des pages.

mais c'est moche. c'est trop compliqué, les pages ont besoin de savoir pour démarrer/arrêter les threads, sinon ça ne marchera pas. donc je suis à la recherche de la bonne façon MVVM pour accomplir cela.

s'il vous plaît aider konstantin

Répondre

1

Il semble que le problème est que le modèle de vue dépend du cycle de vie de la vue - cela implique automatiquement que la vue communiquera le modèle de vue des transitions d'état. L'objectif est de trouver la meilleure représentation de ces changements.

La première étape consiste à recadrer l'interaction: Start() et Stop() sont des concepts impératifs qui, je suis d'accord, se sentent lourds. Au lieu de cela, réfléchissons à ce que nous faisons en tant que machine d'état. Je vais supposer que vos threads font une sorte d'écoute, donc nos états peuvent être Listening, Idle, et Complete. Ils correspondraient respectivement aux threads en cours d'exécution, aux threads en pause et aux threads prêts à être terminés.

Une façon solide pour représenter des états est une énumération:

public enum ListenerState 
{ 
    Idle, 

    Listening, 

    Complete 
} 

Vous déclarer une propriété de ce type sur votre modèle de vue:

public class ListenerModel : ViewModel 
{ 
    private ListenerState _state; 

    public ListenerState State 
    { 
     get { return _state; } 
     set 
     { 
      _state = value; 

      RaisePropertyChanged("State"); 
     } 
    } 
} 

Ensuite, vous écoutiez des changements dans l'état et mettre à jour le fil pour correspondre:

protected override void OnPropertyChanged(PropertyChangedEventArgs e) 
{ 
    if(e.PropertyName == "State") 
    { 
     // Manipulate thread for current state 
    } 
} 

Maintenant, la vue doit juste notifier la vue modèle d'événements du cycle de vie (quelque chose que le modèle de vue ne pouvait pas savoir d'une autre manière en dehors de la vue):

private void OnLoaded(object sender, RoutedEventArgs e) 
{ 
    ((ListenerModel) this.DataContext).State = ListenerState.Listening; 
} 

Si vous voulez découpler complètement la vue du modèle de vue, vous pouvez créer une propriété de dépendance dans votre le contrôle de l'État:

public static readonly DependencyProperty ListenerStateProperty = 
    DependencyProperty.Register("ListenerState", typeof(ListenerState), typeof(YourControl), null); 

public ListenerState ListenerState 
{ 
    get { return (ListenerState) GetValue(ListenerStateProperty); } 
    set { SetValue(ListenerStateProperty, value); } 
} 

Ensuite, définissez cette propriété dans le gestionnaire Loaded au lieu de référencer le modèle de vue:

private void OnLoaded(object sender, RoutedEventArgs e) 
{ 
    this.ListenerState = ListenerState.Listening; 
} 

Enfin, vous wou ld lie la propriété à la propriété du modèle de vue dans le balisage:

<local:YourControl ListenerState="{Binding State, Mode=TwoWay}" />