W takim prostym przykładzie odpowiedź brzmi "tak" (jest to zbyteczne). Ale prawdopodobnie strona będzie zawierała więcej niż jeden obiekt Modelu. Możesz mieć stan strony, a także wiele innych obiektów Modelu, które muszą być wszystkie śledzone. Odbywa się to w ViewModel.
Na przykład użytkownik może mieć dodatkowe informacje o zalogowanym użytkowniku wyświetlanym na pasku stanu, a także usługę uruchomioną w celu wykrycia zmian w pliku tekstowym.
Możesz także mieć formularz do edytowania obiektu Ucznia. Jeśli chcesz zweryfikować te zmiany, nie będziesz chciał bezpośrednio edytować obiektu Ucznia, dopóki modyfikacje nie zostaną zweryfikowane. W takim przypadku ViewModel może działać tymczasowo.
Uwaga na powyższym: To nie jest rzadkością w przypadku walidacji występuje w modelu, ale nawet wtedy będzie prawdopodobnie chcesz, aby użytkownik mógł wprowadzić nieprawidłowe wartości, podczas gdy w procesie edycji formularza. Na przykład, jeśli Twój model nie zezwala na wartość o zerowej długości w polu, nadal chcesz umożliwić użytkownikowi usunięcie wartości, przenieść się do innego pola (powiedzmy na przykład, aby go skopiować), a następnie powrócić do pola i zakończ edycję (wklej). Jeśli jesteś przywiązany bezpośrednio do Modelu, to logika walidacji może nie obsługiwać tego stanu "pomiędzy", "jeszcze nie zakończony", jak chcesz. Na przykład możesz nie chcieć atakować swojego użytkownika błędami walidacji, dopóki nie skończą i nie klikną "Zapisz".
Prawdopodobnie będziesz mieć obiekty poleceń w ViewModelu do obsługi kliknięć przycisków i tym podobnych. Są to obiekty specyficzne dla domeny, które byłyby bezużyteczne w modelu.
ViewModels są również przydatne, gdy trzeba filtrować lub tymczasowo "modyfikować" obiekty modelu, aby uzyskać coś użytecznego na ekranie. Na przykład możesz wyświetlić listę wszystkich użytkowników w systemie wraz z listą dziesięciu najlepszych wykonawców (aktualizowanych co 10 sekund). Możesz również wyświetlić listę raportów i wykres pokazujący całkowity wskaźnik wykorzystania itp. Filtrowanie, sortowanie i dostosowywanie tych danych będzie miało miejsce w ViewModelu.
Model, z drugiej strony, jest zazwyczaj tak czysty, jak to możliwe. Najlepiej, aby tylko POCOs (zazwyczaj) model dokładnie to, co jest w trwałej pamięci (bazy danych, lub co masz). Jeśli Twój magazyn trwały ma pola FirstName i LastName, to także twój model. Tylko w swoim ViewModelu mógłbyś je połączyć, aby uzyskać pole Nazwa ("Pierwszy" lub "Ostatni, Pierwszy" w zależności od potrzeb Widoku).
Na przykład:
namespace Model
{
public class Student
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Class
{
public string Name { get; set; }
public float Score { get; set; }
}
}
namespace ViewModel
{
public class EditStudentRecordViewModel
{
private Model.Student _student;
private IEnumerable<Model.Class> _studentClasses;
/* Bind your View to these fields: */
public string FullName
{
return _student.LastName + ", " + _student.FirstName;
}
public string FirstName { get; set; }
public string LastName { get; set; }
public IEnumerable<Model.Class> PassingClasses
{
get
{
return _studentClasses.Where(c => c.Score >= 78);
}
}
public IEnumerable<Model.Class> FailingClasses
{
get
{
return _studentClasses.Where(c => c.Score < 78);
}
}
public void Save()
{
List<string> l_validationErrors = new List<string>();
if (string.IsNullOrEmpty(this.FirstName))
l_validationErrors.Add("First Name must not be empty.");
if (string.IsNullOrEmpty(this.LastName))
l_validationErrors.Add("Last Name must not be empty.");
if (l_validationErrors.Any())
return;
_student.FirstName = this.FirstName;
_student.LastName = this.LastName;
Model.Utilities.SaveStudent(_student);
}
}
}
Bardzo dobrze postawione pytanie, nawiasem mówiąc: jasne, zwięzłe i zawiera przykładowy kod. – JDB