2011-02-03 3 views
1

Je suis actuellement en train de développer une nouvelle application WPF et j'ai développé la majorité de ma couche de logique métier (ie mes modèles).Considération de conception de MVVM

Je suis sur le point de mettre en œuvre des classes ViewModel pour représenter une caractéristique de mon application. Je suis tout à fait nouveau dans le modèle Model-View-ViewModel et j'ai une question sur l'approche qui serait la meilleure à utiliser lors de l'implémentation de mes classes ViewModel. A partir d'exemples en ligne, j'ai trouvé que souvent le Model est membre du ViewModel. En utilisant cette approche, ViewModel expose les propriétés du membre Model afin qu'elles puissent être liées au modèle dans la vue.

Par exemple:

Public Class MyViewModel 
    Implements INotifyPropertyChanged 

    Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged 

    Private _myModel As ModelClass 

    Public Property MyModelPropertyA As Object 
    Get 
     Return _myModel.MyModelPropertyA 
    End Get 
    Set(ByVal value As Object) 
     _myModel.MyModelPropertyA = value 
     RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("MyModelPropertyA") 
    End Set 
    Public Property MyModelPropertyB As Object 
    Get 
     Return _myModel.MyModelPropertyB 
    End Get 
    Set(ByVal value As Object) 
     _myModel.MyModelPropertyB = value 
     RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("MyModelPropertyB") 
    End Set 
    '.... And so On' 

End Class 

Ce que je n'aime pas cette approche est le fait qu'il ya beaucoup de propriétés que je vais être re-écriture. Par conséquent, je considère l'option Hériter de la classe de modèle dans le ViewModel au lieu d'utiliser un membre privé.

Like So:

Public Class MyViewModel 
     Inherits MyModel 
     Implements INotifyPropertyChanged 

     Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged 

     'Now all of my properties are inherited' 
End Class 

Le problème avec la deuxième approche est que je ne suis pas sûr de savoir comment convertir mes modèles dans les modèles d'affichage alors que l'application est en cours d'exécution.

Vous ne pouvez pas définir viewModelInstance = ModelInstance.

(mais vous pouvez définir modelInstance = viewModelInstance)

Je cherche des conseils sur la meilleure approche sur la façon de mettre en œuvre les classes ViewModel.

+0

Votre utilisation de l'héritage est intéressante. En ce qui concerne votre dernière question, vous auriez besoin d'une usine qui cache la création de l'objet. Un problème que je vois, cependant, est si un objet Modèle apparaît sur deux vues différentes, et a donc deux différents modèles de vue. S'il est déjà instancié en tant que VmA, vous ne pouvez pas le transformer en VmB. – HappyNomad

Répondre

3

Ne pensez même pas à hériter votre viewModel du modèle - ce sera un hack que personne ne voudra. Si vous êtes trop paresseux pour exposer toutes les propriétés (BTW resharper peut le faire automatiquement), vous pouvez inclure votre modèle dans votre viewmodel et lui fournir un accès via une propriété readonly. Mais vous devriez toujours avoir INotifyPropertyChanged implémenté dans la classe du modèle.

Certains code (désolé pour C#):

class Model : INotifyPropertyChanged 
{ 
    public string Name { get; set; } // this raises PropertyChanged 
} 

class ViewModel 
{ 
    private readonly Model _model; 

    public Model Model { get { return _model; } } 
} 

Voir XAML:

<Textbox Text="{Binding Model.Name}" /> 
+0

Il ne s'agit pas d'être paresseux. Il s'agit de respecter un délai serré. Si l'héritage n'est pas la meilleure approche, et que vous croyez qu'il s'agit d'un «hack», alors expliquez pourquoi. – Frinavale

+1

@Frinavale - l'héritage pourrait fonctionner dans votre cas, mais je recommanderais l'ajout de modèle en tant que propriété. Plusieurs inconvénients que je vois dans ce genre d'héritage: ** a) ** Tout d'abord - pour moi, c'est une relation confuse entre M et VM du tout. Comme les livres OOP de base disent que le chien hérite d'Animal parce que le chien est un animal spécifique, mais aucun d'entre eux déclare que le chien doit hériter de la tête parce que les deux ont le nez, les yeux et les oreilles. ** b) ** Votre machine virtuelle reçoit les fonctionnalités de votre modèle (vous ne savez pas si vous en avez), mais imaginez que vous ayez une logique de persistance dans Model, voulez-vous conserver les machines virtuelles? – Snowbear

+0

** c) ** vous ne pourrez pas (au moins sans héritage multiple) hériter votre machine virtuelle d'autre chose. Mes machines virtuelles sont généralement héritées de quelque chose comme 'ViewModelBase' et certaines d'entre elles peuvent être héritées de smth comme' EntityEditorViewModelBase'. Vous vous restreignez en héritant de Model. ** d) ** Vous ne pourrez pas paramétrer votre VM avec votre modèle dans une (!) ligne de code, au lieu de cela vous devrez copier toutes les propriétés (j'espère que vous n'oublierez aucune propriété?) – Snowbear

1

Le ViewModel enveloppements/encapsule généralement relationnelle logique à la vue. L'utilisation d'un ViewModel pour simplement passer à travers les données du modèle n'est pas nécessaire IMHO. Alors qu'une approche puriste serait de définir un ViewModel et de passer ces données à travers; dans certaines circonstances, cela n'est tout simplement pas nécessaire car l'application est de nature simpliste. Si l'application a un potentiel de croissance alors l'utilisation d'un ViewModel serait nécessaire.

Si vous avez un modèle Person; le ViewModel peut généralement contenir une propriété qui expose un ObservableCollection<Person> appelé People. ViewModel est l'orchestrateur de la vue. pas un passage à travers pour le modèle.

Vous ne devez cependant pas lier votre modèle au ViewModel pour les raisons mentionnées ci-dessus car ils devraient être découplés les uns des autres en théorie et en pratique.

+0

L'application devra pouvoir se développer. Cependant, il existe des relations complexes entre les propriétés de mon modèle que j'ai trouvé difficile d'atteindre avec précision en utilisant les convertisseurs et les vues uniquement. J'ai décidé que la meilleure approche serait de créer des modèles de vue pour mes modèles. – Frinavale

+0

@Frinavale "... serait de créer des modèles de vue pour mes modèles ..." ViewModels et modèles ne sont pas 1: 1. Les ViewModels ont généralement une relation de 1: 1 avec la vue. Vous n'avez pas besoin d'un ViewModel pour chaque modèle. créer un seul ViewModel qui peut prendre soin de préparer les données de modèle variables pour la vue –

1

Consultez ce diagramme tiré de here.

enter image description here

C'est un excellent schéma pour désigner afin de vous assurer que vous suivez le modèle correctement. Comme vous pouvez le voir, il existe différentes façons d'interagir entre les couches, mais l'essentiel est cette séparation. Assurez-vous toujours que chaque couche ne connaît que sa couche parent et non ses enfants, c'est-à-dire qu'elle connaît le modèle, mais pas la vue, et que le modèle connaît la couche métier et non le modèle ou la vue. Comme vous pouvez le voir sur les flèches (et comme mentionné ci-dessus), le modèle peut être "exposé à travers une seule propriété sur le viewmodel", ce qui signifie que la vue a un lien direct avec le modèle via le modèle. peut être 'résumé ou ré-implémenté dans les propriétés du modèle' sur le vm.

+0

Juste pour éviter toute confusion, quand je parle de la «couche parente et ses enfants», je ne veux pas dire cela d'une manière hiérarchique oo.J'ai tendance à penser à eux de manière hiérarchique comme Model étant en haut, VM en dessous et ensuite en bas la vue. Ils peuvent chacun regarder mais pas descendre la hiérarchie. – HAdes

Questions connexes