Silverlight - zobacz model
W tym rozdziale przyjrzymy się ważnej technice w rozwoju oprogramowania Silverlight, używaniu View Models.
Plik view model jest kluczowym elementem, który wprowadza technikę zwaną prezentacją oddzielną, oddzielając widok od modelu.
View Models oferują jeden sposób osiągnięcia oddzielnej prezentacji, a zobaczymy, jak wykorzystują powiązanie danych Silverlight, aby zmniejszyć ilość kodu potrzebnego w interfejsie użytkownika.
Wyzwania związane z rozwojem interfejsu użytkownika
View Modelsmają na celu rozwiązanie pewnych problemów, które często pojawiają się podczas tworzenia oprogramowania interfejsu użytkownika. Być może najważniejszym z nich jest to, że kod interfejsu użytkownika jest często trudny do nierozerwalnego przetestowania, szczególnie w przypadku zautomatyzowanych testów jednostkowych. Istnieją również problemy z jakością kodu, które mogą wpływać na ciągłą elastyczność i łatwość utrzymania kodu.
Jeśli podążasz ścieżką najmniejszego oporu, którą prowadzą narzędzia projektowe programu Visual Studio, możesz w końcu umieścić zbyt dużo kodu w kodzie za nim.
Bardzo często spotyka się duże ilości funkcji aplikacji, które są dodawane do kodu znajdującego się za nią.
Niewielu programistów faktycznie planowałoby umieszczenie logiki biznesowej w klasie interfejsu użytkownika, ale ponieważ program Visual Studio umieszcza tam programy obsługi zdarzeń, staje się to zbyt wygodnym miejscem do wykonywania zadań.
Powszechnie przyjmuje się, że oprogramowanie jest łatwiejsze do tworzenia i utrzymywania, jeśli klasy mają dobrze zdefiniowane i odpowiednio wąskie obowiązki.
Zadaniem kodu jest bezpośrednia interakcja z obiektami tworzącymi interfejs użytkownika tam, gdzie jest to konieczne.
Gdy tylko zaczniesz umieszczać kod, który podejmuje decyzje o tym, jak zachowuje się Twoja aplikacja, co zwykle prowadzi do problemów.
Nie tylko logika aplikacji może wpływać do kodu, który powinien być związany z interfejsem użytkownika, niektórzy programiści zaczynają polegać na kontrolkach i innych obiektach interfejsu użytkownika, aby utrzymać ważny stan aplikacji.
Model po prostu przechowuje dane, widok po prostu przechowuje sformatowaną datę, a kontroler (ViewModel) działa jako łącznik między nimi. Kontroler może pobierać dane wejściowe z widoku i umieszczać je na modelu i odwrotnie.
Oddzielna prezentacja
Aby uniknąć problemów spowodowanych umieszczeniem logiki aplikacji w kodzie lub XAML, najlepiej jest użyć techniki znanej jako separated presentation. Mając XAML i kod z minimalną ilością wymaganą do bezpośredniej pracy z obiektami interfejsu użytkownika, klasy interfejsu użytkownika zawierają również kod dla złożonych zachowań interakcji, logiki aplikacji i wszystkiego innego, jak pokazano poniżej po lewej stronie.
Ważne cechy oddzielnej prezentacji -
Dzięki oddzielnej prezentacji klasa interfejsu użytkownika jest znacznie prostsza. Ma oczywiście XAML, ale kod, który za nim stoi, robi tak mało, jak jest to praktyczne.
Logika aplikacji należy do osobnej klasy, która jest często nazywana model.
Wielu deweloperów próbuje użyć powiązania danych, aby połączyć elementy w XAML bezpośrednio z właściwościami w modelu.
Problem w tym model jest całkowicie zajęty kwestiami tego, co robi aplikacja, a nie sposobem interakcji użytkownika z aplikacją.
Większość interfejsów użytkownika ma stan, który nie należy do modelu aplikacji. Na przykład, jeśli twój interfejs użytkownika używa przeciągania i upuszczania, coś musi śledzić rzeczy, takie jak miejsce, w którym jest teraz przeciągany element, jak jego wygląd powinien się zmieniać, gdy przesuwa się nad potencjalnymi celami upuszczania, i jak te cele upuszczania mogą również zmieniają się, gdy element jest nad nimi przeciągany.
Ten rodzaj stanu może stać się zaskakująco złożony i musi zostać dokładnie przetestowany.
W praktyce zwykle chcesz, aby między interfejsem użytkownika a modelem znajdowała się inna klasa. Ma to dwie ważne role.
Po pierwsze, dostosowuje model aplikacji do określonego widoku interfejsu użytkownika.
Po drugie, jest to miejsce, w którym żyje każda nietrywialna logika interakcji, a przez to mam na myśli kod wymagany, aby interfejs użytkownika zachowywał się tak, jak chcesz.
Model / View / ViewModel
View Modelto przykład oddzielnego podejścia do prezentacji, ale wyjaśnijmy dokładnie, jakie rzeczy mamy na każdej warstwie. Istnieją trzy warstwy -
- Model
- View
- ViewModel
Model
To jest classic model obiektowy składający się ze zwykłych klas C #, które nie mają bezpośredniego związku z interfejsem użytkownika.
Zwykle można oczekiwać, że kody modelu będą mogły się kompilować bez odwołań do bibliotek interfejsu użytkownika. W rzeczywistości prawdopodobnie byłbyś w stanie pobrać dokładnie ten sam kod źródłowy i skompilować go do aplikacji Silverlight, zwykłej aplikacji konsoli .NET, a nawet kodu internetowego po stronie serwera.
Typy w modelu powinny reprezentować koncepcje, z którymi współpracuje Twoja aplikacja.
Widok
Widok jest zwykle kontrolką użytkownika, może to być strona główna lub może to być po prostu część Twojej strony.
W większości aplikacji Silverlight dobrym pomysłem jest podzielenie interfejsu użytkownika na małe części definiujące UserControl lub Widok dla każdego elementu.
Aplikacje Silverlight nie są pod tym względem wyjątkowe. Coś, co jest oczywiście specyficzne dla Silverlight, to Widok. Im bardziej szczegółowy jest interfejs użytkownika, tym lepsze są rzeczy. Nie tylko jest mniej prawdopodobne, że potkniesz się o innych programistów pracujących nad tymi samymi plikami, ale utrzymywanie małych i prostych rzeczy w naturalny sposób zniechęca do stosowania skrótów, które prowadzą do kodu przypominającego spaghetti.
Na przykład bardzo często definiuje się plik View do reprezentowania pojedynczego elementu na liście.
ViewModel
Wreszcie dla każdego View, piszesz ViewModel. Jest to więc jedna z ważnych cech plikuViewModel klasa.
Istnieje, aby służyć określonemu poglądowi. PlikViewModel specjalizuje się w określonym sposobie prezentowania rzeczy, takich jak konkretny element danych, który pojawia się na listach.
Dlatego nazywa się to ViewModel; dostosowuje model bazowy specjalnie dla określonego Widoku. Podobnie jak Model,ViewModeljest również zwykłą klasą C #. Nie musi pochodzić z żadnego określonego typu.
Zdarza się, że niektórzy programiści uważają za wygodne umieszczenie niektórych typowych funkcji w podstawowej klasie ViewModel, ale wzorzec tego nie wymaga. W szczególności twójViewModelnie pochodzi z żadnego konkretnego typu Silverlight. Jednak w przeciwieństwie do modelu może używać typów Silverlight w swoich właściwościach.
Na przykład, Twój ViewModel może zdecydować, aby pewne części interfejsu użytkownika były widoczne tylko w określonych warunkach, więc możesz podać właściwość typu System.Windows.Visibility, która jest typem używanym przez elementy Silverlight dla ich właściwości Visibility. Umożliwia to powiązanie widoczności elementu, takiego jak panel, bezpośrednio z ViewModel.
Przykład
Spójrzmy na prosty przykład, w którym będziemy używać Model-View-ViewModel (MVVM) podejście.
Step 1 - Utwórz nowy projekt aplikacji Silverlight SilverlightMVVMDemo.
Step 2 - Dodaj trzy foldery (Model, ViewModel i Views) do projektu, jak pokazano poniżej.
Step 3 - Dodaj klasę StudentModel w folderze Model i wklej poniższy kod w tej klasie.
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 - Dodaj kolejną klasę StudentViewModel do folderu ViewModel i wklej następujący kod.
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 - Dodaj Silverlight User Control klikając prawym przyciskiem myszy Views folder i wybierz Add New Item….
Step 6- Kliknij Dodaj. Teraz zobaczysz plik XAML. Dodaj następujący kod doStudentView.xaml plik, który zawiera różne elementy interfejsu użytkownika.
<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 - Teraz dodaj StudentView do twojego MainPage.xaml plik, jak pokazano poniżej.
<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 - Oto realizacja Loaded wydarzenie w MainPage.xaml.cs plik, który zaktualizuje View z 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 - Kiedy powyższy kod zostanie skompilowany i wykonany, zobaczysz na swojej stronie następujące dane wyjściowe.
Interfejs użytkownika a ViewModel
Jedną z najtrudniejszych części podejścia MVVM jest ustalenie, gdzie powinna przebiegać linia podziału. Nie zawsze jest oczywiste, które rzeczy są gdzie.
W szczególności niektóre elementy interfejsu użytkownika zapewniają funkcjonalność, która według ścisłego widoku prawdopodobnie powinna należeć do ViewModel.
Ogólnie nie wszystkie zachowania zaimplementowane w View są tak ViewModel przyjazny.
Jednym z powodów tego jest brak standardowego sposobu pakowania zachowania ViewModel do ponownego użycia, szczególnie jeśli chcesz użyć środowiska projektowego, takiego jak Visual Studio lub Blend.
Zalety MVVM
MVVM oferuje następujące korzyści -
Rozdzielenie problemów związanych z prezentacją (widok, model widoku, model)
Czysty, testowalny i zarządzalny kod. Może obejmować logikę warstwy prezentacji w testach jednostkowych.
Brak kodu w kodzie, więc warstwa prezentacji i logika są luźno powiązane.
Lepszy sposób wiązania danych.
Wady MVVM
W przypadku prostych interfejsów użytkownika MVVM może być przesadą. Debugowanie byłoby nieco trudne, gdy mamy złożone powiązania danych.