2009-10-05 4 views
2

Considérons une application qui est implémentée en utilisant MVVM, dans laquelle l'utilisateur entre des données.
Lorsque l'utilisateur sélectionne "ouvrir un fichier", "nouveau fichier", etc., l'application demande à l'utilisateur s'il souhaite enregistrer les données dans un fichier avant d'invoquer la commande demandée. Toutefois, si l'utilisateur n'a modifié aucune donnée depuis la dernière sauvegarde, l'application doit ignorer cette question et continuer directement à appeler la commande. Notez que seules les propriétés qui appartiennent au modèle doivent changer d'état. Par exemple, si l'utilisateur a modifié l'élément sélectionné dans une liste (qui modifie la machine virtuelle), il n'est pas nécessaire de l'enregistrer.Besoin d'un bon moyen de gérer l'état - les données ont-elles changé depuis la dernière sauvegarde - sous MVVM

Comment implémenteriez-vous une telle exigence?
L'élévation manuelle d'un événement à chaque modification d'une propriété dans la machine virtuelle semble fastidieuse et source d'erreurs.

Merci, Elad

+0

N'êtes-vous pas déjà levant un événement dans la VM chaque fois qu'une propriété change - l'événement PropertyChanged? Les Viewmodels ne fonctionnent pas très bien si vous ne le faites pas ... –

+0

L'événement PropertyChanged n'est déclenché que lorsque la VM modifie la vue. Toutefois, lorsque l'utilisateur entre des données, il modifie la vue et la liaison modifie la machine virtuelle sans déclencher l'événement PropertyChanged. – Elad

+0

Pouvez-vous s'il vous plaît coller un exemple de votre classe viewmodel? Dans tous les MVVM que j'ai vus, quand la vue change un viewmodel, PropertyChanged est déclenché ... –

Répondre

0

Comment l'utilisation PostSharp?

Je crée 2 attributs:

1. RaisePropertyChanged: INotifyPropertyChanged with postsharp

2. et seconde semblable qui définit seul le drapeau hasChanged:

public class MainWindowViewModel : ViewModel 
{ 
    [RaisePropertyChanged] 
    public string Message { get; set; } 

    [RaisePropertyChanged] 
    [SetsHasChanged] 
    public string DataThatCausesModifyDialog { get; set; } 

    // ... 
} 
+0

Avez-vous eu une bonne expérience avec PostSharp? Je l'ai trouvé pour avoir assez grand succès de la performance, plus cela ne fonctionnait pas dans certaines circonstances. – Elad

+0

J'ai eu une expérience positive avec PostSharp. Il y a un hit de préformance lors de la compilation, car il faut injecter du code supplémentaire en décompilant l'assembly (il a été amélioré en version 1.5). Je pense que ça vaut la peine d'utiliser. –

1

Avec MVVM (en général), chaque classe doit mettre en œuvre INotifyPropertyChanged, et chaque poseur de propriété devrait déclencher une propriété événement a changé:

public class Objective : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 
    private string _text; 

    public string Text 
    { 
     get { return _text; } 
     set 
     { 
      if (_text != value) 
      { 
       _text = value; 
       FirePropertyChanged("Text"); 
      } 
     } 
    } 

    private void FirePropertyChanged(string s) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(s)); 
     } 
    } 
} 

Oui: il est sujet aux erreurs et même avec une utilisation intelligente de lambda, le support du compilateur n'est pas génial. Mais c'est comme cela que MVVM doit être fait, et vous pouvez voir pourquoi sur la plupart des introductions à MVVM.

Pour répondre à votre question, cependant, je vous recommande que vous venez d'ajouter un code personnalisé à votre méthode FirePropertyChanged:

public bool HasChanged { get; set; } 

    private void FirePropertyChanged(string s) 
    { 
     HasChanged = true; 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(s)); 
     } 
    } 

Et vous auriez besoin de se rappeler de mettre hasChanged false après avoir J'ai fini de lire l'objet à partir d'un fichier ou d'une base de données.

10 points si vous pouvez me dire pourquoi HasChanged ne lance pas PropertyChanged, malgré ce que j'ai dit ci-dessus. Cela signifie, bien sûr, que vous ne devriez pas utiliser hasChanged de XAML

edit: Il y a un grand échantillon de ce genre de chose ici: http://follesoe.no/silverlight/divelog/

+0

Rob - avez-vous déclaré HasChanged comme public pour une raison? sûrement il n'aurait pas besoin d'être visible en dehors de la portée de cette machine virtuelle? – kiwipom

+0

N'établissait aucune hypothèse quant au bit de code qui vérifierait la propriété HasChanged et déciderait de présenter un dialogue "DO YOU WANT TO SAVE". –

Questions connexes