Dieser Artikel wurde maschinell übersetzt.

Topaktuelles

Bessere Webformulare mit den MVP-Mustern

Dino Esposito

Dino EspositoSeit die Einführung des Musters Model-View-Controller (MVC) ist ein wichtiger Meilenstein in der Entwicklung von Software. Es wurde gezeigt, dass Entwerfen von Anwendungen mit der Trennung von Bereichen unter Berücksichtigung des Entwicklungsprozesses sowohl für der fertigen Anwendung verbessert. Auch problemlos einen reproduzierbaren Ansatz für das Ablegen dieses Muster in der Praxis.

MVC ist allerdings nicht perfekt, sodass mehrere Varianten im Laufe der Jahre angezeigt wurde.

Da es in den 80er Jahren entwickelt wurde, ist ein Problem, das angezeigt wird, dass MVC-Entwicklung für das Web nicht direkt aufzunehmen. Anpassen von MVC im Web weitere Jahre dauerte und führte zur Entwicklung von spezifischen MVC-Muster wie z. B. Model2. (Model2 ist die aktuelle Geschmacksrichtung von MVC implementiert, indem Castle MonoRail und ASP.NET MVC).

In einem allgemeineren Kontext ist das Model-View-Presenter (MVP)-Muster eine Weiterentwicklung von MVC, die Ansicht und Modell ordentlich, trennt platzieren Sie den Domänencontroller als Vermittler zwischen. Abbildung 1 veranschaulicht das Verhalten einer Anwendung mit dem MVP-Muster entworfen.

Figure 1 Using the MVP Pattern

Abbildung 1 mit dem MVP-Muster

In diesem Artikel werde ich zunächst stellen eine Implementierung mögliche (und relativ standardmäßige) des MVP-Musters für ASP.NET-Web Forms erläutern die Anwendung des Musters, dessen Vorteile für das Team und vergleichen Sie Sie mit ASP.NET MVC und Model-View-ViewModel (MVVM), gemäß der Implementierung in Windows Presentation Foundation (WPF) und Silverlight.

MVP auf einen Blick

MVP ist eine Ableitung von der ursprünglichen MVC-Muster am Taligent (jetzt Bestandteil von IBM), die in den 90er Jahren entwickelt wurde. Das Papier unter wildcrest.com/Potel/Portfolio/mvp.pdf-heruntergeladen bietet eine gute Einführung in MVP und die Ideen dahinter.

Der Ersteller des MVP getrennt ordentlich das Modell (die Daten, auf die in der Ansicht bearbeitet) aus der Ansicht/Controller-Paar. Sie werden auch den Controller als Vortragenden die Idee zu betonen, dass das Muster, die Rolle des Controllers, Vermittler zwischen dem Benutzer und die Anwendung wird umbenannt. Der Presenter ist die Komponente, die “ zeigt ” die Benutzeroberfläche für dem Benutzer und Befehle vom Benutzer akzeptiert. Der Kursleiter enthält die meisten der Darstellungslogik und weiß, wie für den Umgang mit der Ansicht und dem Rest des Systems, einschließlich der Back-End-Dienste und Datenebenen.

Ein wichtiger Innovationen in MVP ist die Tatsache, dass die Details der Ansicht einer Schnittstelle (oder Basisklasse) abstrahiert werden. Der Presenter kommuniziert mit einer Abstraktion der Ansicht, die der Vortragende selbst eine hochgradig wiederverwendbare und hochgradig prüfbare Klasse macht. Auf diese Weise können zwei interessante Szenarios.

Zunächst ist die Darstellungslogik unabhängig von der UI-Technologie verwendet wird. Folglich konnte der gleiche Controller in Windows- und Webanwendungen Darstellungsschichten wiederverwendet werden. Am Ende der Vortragende gegen eine Schnittstelle codiert ist und es an ein beliebiges Objekt, das die Schnittstelle verfügbar macht, kommunizieren kann –, ob ein Windows Forms-Objekt, ein ASP.NET Page-Objekt oder ein WPF-Window-Objekt.

Zweitens kann der gleiche Presenter mit verschiedenen Ansichten der gleichen Anwendung arbeiten. Dies ist eine wichtige Leistung in Bezug auf die Software als ein Service (SaaS) Szenarien, in denen eine Anwendung auf einem Webserver gehostet und als Dienst angeboten wird, um Kunden, jedes seine eigene angepasste Benutzeroberfläche erforderlich ist.

Es versteht sich von selbst, dass beide Vorteile nicht unbedingt in allen Situationen anwendbar sind. Gibt an, ob diese profitieren vor allem auf die Anwendung abhängig ist und Sie erwarten, dass Ihre Windows- und Webanwendungen vor einsetzen Navigationslogik enden. Wenn die Logik identisch ist, können Sie es über das MVP-Modell verwenden.

MVP in Aktion

Wenn das MVP-Muster zu implementieren, ist der erste Schritt die Abstraktion für jede erforderliche Ansicht definieren. Jede Seite in einer ASP.NET-Anwendung und jede Anwendung Formular in einer Windows (oder WPF/Silverlight) haben eine eigene Schnittstelle für die Kommunikation mit den restlichen die Präsentationsebene sind. Die Schnittstelle identifiziert das Datenmodell, das die Ansicht unterstützt. Jede Ansicht logisch gleichwertig haben die gleiche Schnittstelle unabhängig von der Plattform.

Die Abstraktion der Ansicht umfasst das Modell, das die Ansicht erkennt und funktioniert bei und kann mit einigen ad-hoc-Methoden und Ereignisse nützlich, um eine reibungslose Interaktion zwischen der Kursleiter und die Ansicht zu bevorzugen erweitern. Abbildung 2 zeigt eine mögliche Abstraktion für die Ansicht gerendert in Abbildung 3 , die von einer einfachen Aufgabe Liste Anwendung verwendet wird.

Abbildung 2 ein Beispiel für eine Ansicht Abstraction

public interface IMemoFormView {
  String Title { get; set; }
  String Summary { get; set; }
  String Location { get; set; }
  String Tags { get; set; }
  DateTime BeginWithin { get; set; }
  DateTime DueBy { get; set; }
  String Message { get; set; }
  Int32 GetSelectedPriorityValue();
  void FillPriorityList(Int32 selectedIndex);
  Boolean Confirm(String message, String title);
  void SetErrorMessage(String controlName);
}

Abbildung 3 nun auch übereinstimmen, Elemente der Benutzeroberfläche wie visuelle Elemente im Formular angezeigt.

Figure 3 Binding Members of the Interface to Visual Elements

Abbildung 3 Member der Schnittstelle in Visual-Elemente binden

Der grundlegende Punkt ist, dass Interaktion zwischen dem Vortragenden und die Benutzeroberfläche über den Vertrag der Ansicht erfolgen muss. Eine Schaltfläche, die durch Klicken auf eine beliebige Auswahl muss Eingabe an den Vortragenden weitergeleitet und verarbeitet werden vorhanden. Wenn der Presenter zum Abfragen von Daten in der Ansicht oder zum Übergeben von Daten an die Ansicht muss, sollte es eine Methode in der Schnittstelle, die zu berücksichtigen.

Implementieren den Vertrag anzeigen

Die Schnittstelle, die die Ansicht muss durch die Klasse implementiert werden, die die Ansicht selbst darstellt. Wie bereits erwähnt, wird die Ansichtsklasse der Seite in ASP.NET das Formular im Windows Forms, die Fenster in WPF und das Benutzersteuerelement in Silverlight. Abbildung 4 zeigt ein Beispiel für Windows Forms.

Abbildung 4 eine mögliche Implementierung der View-Klasse

public partial class MemoForm : Form, IMemoFormView {
  public string Title {
    get { return memoForm_Text.Text; }
    set { memoForm_Text.Text = value; }
    ...
  }
  public DateTime DueBy {
    get { return memoForm_DueBy.Value; }
    set { memoForm_DueBy.Value = value; }
  }
  public int GetSelectedPriorityValue() {
    var priority = 
      memoForm_Priority.SelectedItem as PriorityItem;
    if (priority == null)
      return PriorityItem.Default;
    return priority.Value;
  }
  public void FillPriorityList(int selectedIndex) {
    memoForm_Priority.DataSource = 
      PriorityItem.GetStandardList();
    memoForm_Priority.ValueMember = "Value";
    memoForm_Priority.DisplayMember = "Text";
    memoForm_Priority.SelectedIndex = selectedIndex;
  }
  public void SetErrorMessage(string controlName) {
    var control = this.GetControlFromId(controlName);
    if (control == null)
      throw new NullReferenceException(
        "Unexpected null reference for a form control."); 
    memoForm_ErrorManager.SetError(control, 
      ErrorMessages.RequiredField);
  }
  ...
}

Wie Sie sehen können, werden Eigenschaften als Wrapper für einige Eigenschaften auf visuelle Steuerelemente implementiert.Beispielsweise ist die Title-Eigenschaft als Wrapper für die Text-Eigenschaft eines TextBox-Steuerelements.Ebenso wird DueBy-Eigenschaft die Value-Eigenschaft eines Kalender-Steuerelements umbrochen.Die Schnittstelle abschirmt noch wichtiger ist die Presenter-Klasse von den Details der Benutzeroberfläche für eine bestimmte Plattform.Jedes Objekt kann die gleiche Presenter-Klasse erstellt, um die Interaktion mit der Benutzeroberfläche IMemoFormView verarbeiten, die die Schnittstelle blissfully ignoriert die Details der Programmierschnittstelle des zugrunde liegenden Steuerelemente implementiert.

Wie würden Sie mit UI-Elementen arbeiten, die eine Auflistung von Daten, z. B. ein Dropdown-Listenfeld?Verwenden Sie die Datenbindung (z. B. in Abbildung 4 ) oder sollten Sie entscheiden, für einen einfacheren Ansatz, der die Ansicht passiven und frei von allen Darstellungslogik verwaltet?

Das ist für Sie.Als Reaktion auf diese Art von Fragen, hat das MVP-Muster in zwei separaten Muster geteilt wurde – Supervising Controller und passiven Ansicht –, deren primäre Unterschied besteht darin, nur die Menge an Code in der Ansicht.Mithilfe von Datenbindung zum Auffüllen der Benutzeroberfläche (siehe Abbildung 4 ) Fügt eine Präsentationslogik zur Ansicht und würde Sie die Sorte von einem supervising Controller zu erhalten.

Weitere Logik haben Sie in der Ansicht, desto sollten Sie Tests interessieren.Ein, und Testen einen Teil der Benutzeroberfläche ist eine Aufgabe, die problemlos kann nicht automatisiert werden.Für einen supervising Controller bzw. sich Nachricht entscheiden für eine Ansicht dünner und dumber ist lediglich ein Urteil-Aufruf.

Die Presenter-Klasse

Die Steuerelemente in der Ansicht alle Benutzerstiftbewegung zu erfassen und Auslösen ein Ereignisses zur Ansicht, wie z. B. ein Schaltflächenklick oder eine Änderung der ausgewählten Index.Die Ansicht enthält einfache Ereignishandler, die dispatch-Aufruf an den Vortragenden, die verantwortlichen der Ansicht ist.Wenn die Ansicht zum ersten Mal geladen wird, wird eine Instanz der Presenter-Klasse erstellt und speichert, die intern als Private Member.Abbildung 5 zeigt den typischen Konstruktor eines Windows Forms.

Abbildung 5 Erstellen eines Formulars MVP

public partial class Form1 : 
  Form, ICustomerDetailsView {
  private MemoFormPresenter presenter;
  public Form1() {
    // Framework initialization stuff
    InitializeComponent();
    // Instantiate the presenter
    presenter = new MemoFormPresenter(this);
    // Attach event handlers
    ...
  }
  private void Form1_Load(
    object sender, EventArgs e) {
    presenter.Initialize();
  }
  ...
}

Die Presenter-Klasse erhält in der Regel einen Verweis auf die Ansicht über seinen Konstruktor. Die Ansicht enthält einen Verweis auf den Vortragenden und der Kursleiter enthält einen Verweis auf die Ansicht. Der Presenter weiß allerdings die Ansicht nur durch den Vertrag. Der Presenter funktioniert segregating jedes Ansichtsobjekt es um die verkürzte View-Schnittstelle empfängt. Abbildung 6 veranschaulicht die Grundlagen für die Presenter-Klasse.

Abbildung 6 A Sample Presenter-Klasse

public class MemoFormPresenter {
  private readonly IMemoFormView view;
  public MemoFormPresenter(IMemoFormView theView) {
    view = theView;
    context = AppContext.Navigator.Argument 
      as MemoFormContext;
    if (_context == null)
      return;
  }
 
  public void Initialize() {
    InitializeInternal();
  }
  private void InitializeInternal() {
    int priorityIndex = _context.Memo.Priority;
    if (priorityIndex >= 1 && priorityIndex <= 5)
      priorityIndex--;
    else
      priorityIndex = 2;
    if (_context.Memo.BeginDate.HasValue)
      _view.BeginWithin = _context.Memo.BeginDate.Value;
    if (_context.Memo.EndDate.HasValue)
      _view.DueBy = _context.Memo.EndDate.Value;
      _view.FillPriorityList(priorityIndex);
      _view.Title = _context.Memo.Title;
      _view.Summary = _context.Memo.Summary;
      _view.Tags = _context.Memo.Tags;
      _view.MemoLocation = _context.Memo.Location;
  }
  ...
}

Der Konstruktor empfängt und speichert den Verweis auf die Ansicht und initialisiert die Ansicht mithilfe der öffentlichen Schnittstelle vom Vertrag dargestellt. Das Kontextobjekt Sie finden in den Code des Abbildung 6 verwendet wird alle Eingabedaten Vortragenden vom Aufrufer erhalten, um die Ansicht zu initialisieren muss. Diese Informationen sind nicht in allen Fällen erforderlich, aber es stellt sich heraus, die erforderlich sein, wenn Sie das Formular, verwenden um Daten zu bearbeiten oder Dialogfelder zum Anzeigen einiger Informationen vorliegen.

Beim Initialisieren der Ansicht ist genauso einfach wie das Zuweisen von Werten zu den Membern einer Klasse, abgesehen davon, dass eine Zuordnung eines Updates jetzt an die Benutzeroberfläche führt.

Die Presenter-Klasse enthält auch eine Reihe von Methoden, die als Reaktion auf Anforderungen von der Benutzeroberfläche ausführen. Maßnahmen auf oder der Benutzer ist auf die Presenter-Klasse an eine Methode gebunden:

private void memoForm_OK_Click(
  object sender, EventArgs e) {
  presenter.Ok();
}

Die Presenter-Methode greift den Ansicht Verweis auf Eingabewerten und aktualisiert die Benutzeroberfläche auf die gleiche Weise.

Der Presenter ist auch für die Navigation innerhalb der Anwendung verantwortlich. Insbesondere ist der Kursleiter für aktivieren (oder deaktivieren) Sub-views und Befehl Navigation zur nächsten Ansicht verantwortlich.

Ein Sub-view ist im Wesentlichen eine Teilmenge der Ansicht. Es ist in der Regel einen Bereich, der erweitert oder reduziert die Übereinstimmung mit dem Kontext oder vielleicht ein untergeordnetes Fenster werden kann – entweder modal oder nicht modal. Der Presenter steuert die Sichtbarkeit der Sub-views über Member (hauptsächlich Boolean Elemente) auf die View-Schnittstelle.

Was ist die Steuerung an eine andere Ansicht (und Presenter) übertragen? Erstellen Sie eine statische Klasse, die den Anwendung Controller – d. h. die zentrale Konsole, der die Logik für die nächste Ansicht zu bestimmen. Abbildung 7 zeigt das Diagramm des Controllers Anwendung.

Figure 7 The Application Controller

Abbildung 7 der Application Controller

Die Controller-Anwendungsklasse repräsentiert die Shell die Vortragenden Aufrufen an anderer Stelle zu navigieren. Diese Klasse wird NavigateTo-Methode verfügen, die den Workflow, implementiert bestimmt, dass die nächste Ansicht oder, einfach zu der angegebenen Ansicht wechselt. Der Workflow kann alles sein – so komplex wie eine reale Workflow oder einfach eine Folge von IF-Anweisungen. Die Logik des Workflows statisch in der Anwendung Controller fest codiert oder importiert werden kann aus einer externen und austauschbare Komponente (siehe Abbildung 8 ).

Abbildung 8 Implementierung von einem Application Controller

public static class ApplicationController {
  private static INavigationWorkflow instance;
  private static object navigationArgument;
  public static void Register(
    INavigationWorkflow service) {
    if (service == null)
      throw new ArgumentNullException();
    instance = service;
  }
  public static void NavigateTo(string view) {
    if (instance == null)
      throw new InvalidOperationException();
    instance.NavigateTo(view);      
  }
 
  public static void NavigateTo(
    string view, object argument) { 
    if (instance == null)
      throw new InvalidOperationException();
    navigationArgument = argument;
    NavigateTo(view);
 }
 public static object Argument {
   get { return navigationArgument; }
 }
}

Die tatsächliche Navigationslogik in der Workflow-Komponente wird eine plattformspezifische-Lösung verwenden, um zu einer anderen Ansicht zu wechseln. Für Windows Forms verwenden Sie Methoden zum Öffnen und Anzeigen von Formularen, die in ASP.NET verwenden Sie die Redirect-Methode auf das Response-Objekt.

MVP und ASP.NET MVC

ASP.NET MVC basiert auf eine Geschmacksrichtung des MVC-Musters, das ein paar Dinge mit MVP gemeinsam hat. Der MVC-Controller ist ein Vermittler zwischen der Ansicht und dem Back-End. Der Controller nicht enthalten einen Verweis auf die Ansicht, aber ein Modell-Objekt füllt und übergibt, das der Ansicht mit die Diensten der intermediate-Komponente – das Modul anzeigen.

In einer Weise wird die Ansicht durch das Objektmodell abstrahiert, deren Struc ­ Ture die Merkmale der Sicht und seine Benutzeroberfläche widerspiegelt. Navigation wird durch den Controller verwaltet die nächste Ansicht aus dem Kontext jeder Aktion auswählt. Eine integrierte Logik verwendet wird. Die Logik sollte besonders komplex ist, für einen bestimmten Controller-Methode – gesagt nicht etwas, das jeden Tag ausgeführt werden – führen Sie immer eine Workflow-Komponente, die bestimmt, die nächste Ansicht auswählen.

Was ist mit Webformularen? Durch Web Forms eignet sich gut zum Host ein MVP-Implementierung. Jedoch ist es sollte klar, dass alle erhalten Sie ist das Hinzufügen von Ebenen im Kontext des Postbacks. Alles vor dem Postback eingebunden werden, noch können alle Elemente, die nach dem Postbackereignis auftritt. Eine vollständige Implementierung der MVP, die erweitert, wird um den vollständigen Lebenszyklus decken ist nicht möglich, in Web Forms, aber die Ebene der Testbarkeit wesentlich erhöht und ist eine gute Sache selbst MVP hinzufügen, um das postback
der Web Forms-Seiten.

MVP und MVVM

Worüber, stattdessen MVP und MVVM im Kontext von WPF und Silverlight-Anwendungen? MVVM ist eine Variation des MVP, auch bekannt als Presentation-Modell. Die Idee ist, dass das Ansicht-Modell in der Presenter-Klasse integriert wird und die Presenter-Klasse verfügbar macht die öffentlichen Member, die die Ansicht gelesen und geschrieben werden. Dies geschieht durch bidirektionale Datenbindung. Sie können am Ende des Tages MVVM als eine besondere Geschmacksrichtung des MVP besonders geeignet, um umfangreiche Benutzeroberflächen und Frameworks (z. B. WPF), die diese Möglichkeit heraufstufen aufrufen.

In MVVM der Ansicht ist auf Eigenschaften der Presenter-Klasse (Ansicht-Modell) datengebunden. Alles, was der Benutzer aktualisiert diese Eigenschaften in der Vortragende. Alle Anfragen vom Benutzer (Befehle in WPF) werden über eine Methode für die Presenter-Klasse behandelt. Alle Ergebnisse die Presenter-Methode berechnet im Modell Ansicht gespeichert und über die Datenbindung an die Ansicht zur Verfügung gestellt. In WPF und Silverlight kann nichts, das verhindert, dass eine manuelle Implementierung von dem MVP-Muster verwendet werden. Jedoch herausstellt es diese Tools wie z. B. Blend es noch vereinfachen wird effektive MVVM über Datenbindung verwenden.

Postback

MVP enthält Anleitungen zum Verwalten von Heaps der Ansichten und kommt ganz offensichtlich zu Kosten: die Kosten der erhöhten Komplexität im Anwendungscode. Wie Sie sich vorstellen können, sind diese Kosten besser in großen Anwendungen als in einfachen Programmen absorbieren. MVP und ist daher nicht nur für jede Anwendung. Können basierend auf einem Vertrag, der die Ansicht darstellt, MVP für Designer und Entwickler, parallel zu arbeiten, die immer eine gute Sache in jedem Entwicklungsszenario ist. MVP hält die Presenter-Klasse als eigenständiges und von der Ansicht isoliert. In Web Forms stellt MVP die nur sinnvolle Möglichkeit Testbarkeit mindestens den Code hinzu, das das Postback ausgeführt wird.

Dino Esposito ist Autor des bald bei Microsoft Press erscheinenden Titels „Programming Microsoft ASP.NET MVC“ und Mitverfasser des Titels „Microsoft .NET: (Microsoft Press, 2008) beteiligt. Esposito lebt in Italien und ist ein weltweit gefragter Referent bei Branchenveranstaltungen. Sie finden seinen Blog unter weblogs.asp.net/despos.

Dank an den folgenden technischen Experten für die Überprüfung dieser Artikel: Don Smith and Josh Smith