Silverlight - Voir le modèle
Dans ce chapitre, nous examinerons une technique importante du développement logiciel de Silverlight, l'utilisation de View Models.
le view model est un élément clé, qui introduit une technique appelée présentation séparée en gardant la vue séparée du modèle.
View Models offrent un moyen de réaliser une présentation séparée, et nous verrons comment ils exploitent la liaison de données de Silverlight pour réduire la quantité de code nécessaire dans votre interface utilisateur.
Défis de développement de l'interface utilisateur
View Modelssont conçus pour résoudre certains problèmes fréquemment rencontrés lors du développement d'un logiciel d'interface utilisateur. Le plus important est peut-être que le code de l'interface utilisateur est souvent difficile à tester de manière inextricable, en particulier avec les tests unitaires automatisés. Il existe également des problèmes de qualité du code qui peuvent affecter la flexibilité et la maintenabilité continues de votre code.
Si vous suivez le chemin de moindre résistance que les outils de conception de Visual Studio vous conduisent, vous pouvez finir par mettre beaucoup trop de code dans le code derrière.
Il est très courant de voir de grandes quantités de fonctionnalités d'application sont ajoutées dans le code derrière.
Peu de développeurs envisagent de placer la logique métier dans une classe d'interface utilisateur, mais comme c'est là que Visual Studio place vos gestionnaires d'événements, cela devient un endroit trop pratique pour faire avancer les choses.
Il est largement admis que les logiciels sont plus faciles à développer et à maintenir si les classes ont des responsabilités bien définies et raisonnablement étroites.
Le travail de code derrière est d'interagir directement avec les objets qui composent l'interface utilisateur là où c'est nécessaire.
Dès que vous commencez à mettre du code qui prend des décisions sur le comportement de votre application, ce qui a tendance à poser des problèmes.
Non seulement la logique de l'application peut couler dans le code censé être concerné par l'interface utilisateur, mais certains développeurs commencent à s'appuyer sur des contrôles et d'autres objets d'interface utilisateur pour conserver un état d'application important.
Le modèle contient simplement les données, la vue contient simplement la date formatée et le contrôleur (ViewModel) sert de liaison entre les deux. Le contrôleur peut prendre une entrée de la vue et la placer sur le modèle et vice versa.
Présentation séparée
Pour éviter les problèmes causés par l'insertion de la logique d'application dans le code derrière ou XAML, il est préférable d'utiliser une technique appelée separated presentation. Ayant XAML et code derrière avec le minimum requis pour travailler directement avec des objets d'interface utilisateur, les classes d'interface utilisateur contiennent également du code pour les comportements d'interaction complexes, la logique d'application et tout le reste, comme indiqué ci-dessous sur le côté gauche.
Caractéristiques importantes de la présentation séparée -
Avec une présentation séparée, la classe d'interface utilisateur est beaucoup plus simple. Il a XAML bien sûr, mais le code derrière fait aussi peu que pratique.
La logique d'application appartient à une classe distincte, souvent appelée model.
De nombreux développeurs tentent d'utiliser la liaison de données pour connecter des éléments dans le XAML directement aux propriétés du modèle.
Le problème est le model est entièrement préoccupé par ce que fait l'application, et non par la manière dont l'utilisateur interagit avec l'application.
La plupart des interfaces utilisateur ont un état qui n'appartient pas au modèle d'application. Par exemple, si votre interface utilisateur utilise un glisser-déposer, quelque chose doit garder une trace de choses comme l'endroit où l'élément à glisser est maintenant, comment son apparence devrait changer lorsqu'il se déplace sur les cibles de dépôt possibles, et comment ces cibles de dépôt pourraient également changer au fur et à mesure que l'élément est glissé dessus.
Ce type d'état peut devenir étonnamment complexe et doit être minutieusement testé.
En pratique, vous voulez normalement une autre classe assise entre l'interface utilisateur et le modèle. Cela a deux rôles importants.
Tout d'abord, il adapte votre modèle d'application à une vue d'interface utilisateur particulière.
Deuxièmement, c'est là que réside toute logique d'interaction non triviale, et par là, je veux dire le code nécessaire pour que votre interface utilisateur se comporte comme vous le souhaitez.
Modèle / Vue / VueModèle
View Modelest un exemple de l'approche de présentation séparée, mais soyons clairs sur le type de chose que nous avons dans chaque couche. Il y a trois couches -
- Model
- View
- ViewModel
Modèle
C'est un classic modèle d'objet comprenant des classes C # ordinaires qui n'ont pas de relation directe avec l'interface utilisateur.
Vous vous attendez généralement à ce que vos codes de modèle puissent être compilés sans références à aucune bibliothèque d'interface utilisateur. En fait, vous seriez probablement en mesure de prendre exactement le même code source et de le compiler dans une application Silverlight, une application de console .NET ordinaire ou même un code Web côté serveur.
Les types du modèle doivent représenter les concepts avec lesquels votre application fonctionne.
Vue
Une vue est normalement un UserControl, ce peut être votre MainPage ou simplement une partie de votre page.
Dans la plupart des applications Silverlight, il est judicieux de diviser votre interface utilisateur en petits morceaux définissant un UserControl ou une vue pour chaque élément.
Les applications Silverlight ne sont pas uniques à cet égard. Quelque chose qui est évidemment spécifique à Silverlight est la vue. Plus votre interface utilisateur est fine, meilleures sont les choses. Non seulement vous êtes moins susceptible de trébucher sur d'autres développeurs travaillant sur les mêmes fichiers, mais garder les choses petites et simples décourage naturellement les raccourcis qui mènent au code de type spaghetti.
Par exemple, il est très courant de définir un View pour représenter un élément individuel dans une liste.
VoirModèle
Enfin, pour chaque View, vous écrivez un ViewModel. C'est donc l'une des caractéristiques importantes d'unViewModel classe.
Il existe pour servir une vue particulière. leViewModel est spécialisé pour une manière particulière de présenter les choses, comme un élément de données particulier tel qu'il apparaît dans les listes.
C'est pourquoi on l'appelle un ViewModel; il adapte le modèle sous-jacent en particulier pour une vue particulière. Comme le modèle, leViewModelest également une classe C # ordinaire. Il n'a pas besoin de dériver d'un type particulier.
En l'occurrence, certains développeurs trouvent pratique de mettre des fonctionnalités communes dans une classe de base ViewModel, mais le modèle ne l'exige pas. En particulier, votreViewModelne dérive d'aucun type spécifique à Silverlight. Cependant, contrairement au modèle, il peut utiliser des types Silverlight dans ses propriétés.
Par exemple, votre ViewModel peut choisir de rendre certaines parties de votre interface utilisateur visibles uniquement dans certaines conditions, et vous pouvez donc fournir une propriété de type System.Windows.Visibility, qui est le type que les éléments Silverlight utilisent pour leur propriété Visibility. Cela permet de lier la visibilité d'un élément, tel qu'un panneau, directement au ViewModel.
Exemple
Regardons un exemple simple dans lequel nous utiliserons Model-View-ViewModel (MVVM) approche.
Step 1 - Créer un nouveau projet d'application Silverlight SilverlightMVVMDemo.
Step 2 - Ajoutez les trois dossiers (Model, ViewModel et Views) dans votre projet comme indiqué ci-dessous.
Step 3 - Ajoutez une classe StudentModel dans le dossier Model et collez le code ci-dessous dans cette classe.
using System.ComponentModel;
namespace SilverlightMVVMDemo.Model {
public class StudentModel {}
public class Student : INotifyPropertyChanged {
private string firstName;
private string lastName;
public string FirstName {
get { return firstName; }
set {
if (firstName != value) {
firstName = value;
RaisePropertyChanged("FirstName");
RaisePropertyChanged("FullName");
}
}
}
public string LastName {
get { return lastName; }
set {
if (lastName != value) {
lastName = value;
RaisePropertyChanged("LastName");
RaisePropertyChanged("FullName");
}
}
}
public string FullName {
get {
return firstName + " " + lastName;
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
}
Step 4 - Ajoutez une autre classe StudentViewModel dans le dossier ViewModel et collez le code suivant.
using SilverlightMVVMDemo.Model;
using System.Collections.ObjectModel;
namespace SilverlightMVVMDemo.ViewModel {
public class StudentViewModel {
public ObservableCollection<Student> Students {
get;
set;
}
public void LoadStudents() {
ObservableCollection<Student> students = new ObservableCollection<Student>();
students.Add(new Student { FirstName = "Mark", LastName = "Allain" });
students.Add(new Student { FirstName = "Allen", LastName = "Brown" });
students.Add(new Student { FirstName = "Linda", LastName = "Hamerski" });
Students = students;
}
}
}
Step 5 - Ajouter Silverlight User Control en faisant un clic droit sur Views dossier et sélectionnez Add New Item….
Step 6- Cliquez sur Ajouter. Vous verrez maintenant le fichier XAML. Ajoutez le code suivant dansStudentView.xaml fichier, qui contient différents éléments de l'interface utilisateur.
<UserControl x:Class = "SilverlightMVVMDemo.Views.StudentView"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable = "d"
d:DesignHeight = "300" d:DesignWidth = "400">
<Grid x:Name = "LayoutRoot" Background = "White">
<StackPanel HorizontalAlignment = "Left">
<ItemsControl ItemsSource = "{Binding Path=Students}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation = "Horizontal">
<TextBox Text = "{Binding Path = FirstName, Mode = TwoWay}"
Width = "100" Margin = "3 5 3 5"/>
<TextBox Text = "{Binding Path = LastName, Mode = TwoWay}"
Width = "100" Margin = "0 5 3 5"/>
<TextBlock Text = "{Binding Path = FullName, Mode=OneWay}"
Margin = "0 5 3 5"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
</UserControl>
Step 7 - Ajoutez maintenant le StudentView Dans votre MainPage.xaml fichier comme indiqué ci-dessous.
<UserControl x:Class = "SilverlightMVVMDemo.MainPage"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views = "clr-namespace:SilverlightMVVMDemo.Views"
mc:Ignorable = "d"
d:DesignHeight = "576.316" d:DesignWidth = "863.158">
<Grid x:Name = "LayoutRoot" Background = "White">
<views:StudentView x:Name = "StudentViewControl" Loaded = "StudentViewControl_Loaded"/>
</Grid>
</UserControl>
Step 8 - Voici la mise en œuvre de Loaded événement dans le MainPage.xaml.cs fichier, qui mettra à jour le View du ViewModel.
using System.Windows;
using System.Windows.Controls;
namespace SilverlightMVVMDemo {
public partial class MainPage : UserControl {
public MainPage() {
InitializeComponent();
}
}
private void StudentViewControl_Loaded(object sender, RoutedEventArgs e) {
SilverlightMVVMDemo.ViewModel.StudentViewModel
studentViewModelObject = new SilverlightMVVMDemo.ViewModel.
StudentViewModel();
studentViewModelObject.LoadStudents();
StudentViewControl.DataContext = studentViewModelObject;
}
}
Step 9 - Lorsque le code ci-dessus est compilé et exécuté, vous verrez la sortie suivante sur votre page Web.
UI vs ViewModel
L'une des parties les plus difficiles de l'approche MVVM consiste à déterminer où doit se situer la ligne de démarcation. Il n'est pas toujours évident de savoir à quelles choses appartiennent.
En particulier, certains éléments de l'interface utilisateur fournissent des fonctionnalités qui, selon une vue stricte, devraient sans doute appartenir au ViewModel.
En général, tous les comportements mis en œuvre dans le View sont tellement ViewModel amical.
Cela s'explique en partie par le fait qu'il n'existe aucun moyen standard de regrouper le comportement de ViewModel pour la réutilisation, en particulier si vous souhaitez utiliser un environnement de conception, tel que Visual Studio ou Blend.
Avantages de MVVM
MVVM offre les avantages suivants -
Séparation des problèmes de présentation (View, ViewModel, Model)
Code propre testable et gérable. Peut inclure une logique de niveau de présentation dans les tests unitaires.
Aucun code derrière le code, donc la couche de présentation et la logique sont faiblement couplées.
Meilleur moyen de liaison de données.
Inconvénients de MVVM
Pour les interfaces utilisateur simples, MVVM peut être excessif. Le débogage serait un peu difficile lorsque nous avons des liaisons de données complexes.