Frage

Ich habe implementiert eine MVP Triade mit dem passiven Ansicht Muster - das heißt, die Ansicht enthält nur einfache Getter und Setter. Allerdings Probleme Ich habe die Sichtdaten und Modelldaten seperating. Insbesondere beim Umgang mit einer Änderung in dem Ansichtszustand.

Die Triade wird verwendet, um den Benutzer zu ermöglichen, einen Teil aus einer Liste auszuwählen. Die Liste der Teile wird durch das Modell mit jedem Teil geliefert eindeutig durch eine eindeutige ID gekennzeichnet.

Nehmen wir die Teile wie folgt aussehen:

class Part
{
    int ID; // this code uniquely identifies the part within the model
    String partCode;
    String description;
    double voltage;
}

Die Ansicht zeigt die Liste an den Benutzer und ermöglicht es ihnen, einen Teil wählen

Die Liste wird in einem Datagridview angezeigt und ein Teil durch einen Klick auf einer Zeile in der Datagridview ausgewählt ist.

Die ID wird den Benutzer nicht angezeigt werden, und weder ist die Spannung, deshalb schafft das Modell eine Datentabelle, die nur die partCode und Beschreibung enthält. Diese Datentabelle durch die Vortragende zu einer Eigenschaft auf der Ansicht, dass die Karten an der Datasource Eigenschaft des Datagridview zugeordnet ist.

class Presenter
{
    IView _view;
    IModel _model;

    //...///

    _view.Data = _model.GetFilteredData();
}

class Model
{
    public DataTable GetFilteredData()
    {
        // create a DataTable with the partCode and Description columns only
        // return DataTable
    } 
}

class View  //winform
{
      public DataTable Data
      {
          set 
          {
              this.dataGridView.Source = value;
          }
      }
}

So weit, so gut. Die Ansicht dislays die gefilterten Daten im Datagridview.

Das Problem, das ich habe, ist das Teil durch den Benutzer ausgewählt zurück.

Die Ansicht hat keine Kenntnis über die eindeutige ID, da es nicht angezeigt wird und die anderen Informationen nicht eindeutig sein garantiert werden -. Therfore es nicht möglich ist, eindeutig zu identifizieren ausgewählt, um den Teil

Im Wesentlichen Ansichtsdaten (die ausgewählte Zeile) auf Modelldaten (der ausgewählten Teil) ohne eine Komponente mit den anderen Daten.

ich versuche zu konvertieren

Bisher habe ich folgende Lösungen:

1) Die Ansicht wird eine Datentabelle übergeben, der die ID enthält und filtert dann die Anzeige so, dass es den Benutzer nicht angezeigt wird. Es ist dann trivial eine ID für die ausgewählte Zeile zurückzukehren. Das Problem hier ist, dass ich jetzt die Ansicht mit Logik verunreinigt haben, die nicht getestet ist (die Filterung der Anzeige).

2) Die Ansicht gibt den Zeilenindex und das Modell paßt diesen Index auf eine Zeile in den ursprünglichen Daten. Dies würde bedeuten, um sicherzustellen, dass die Reihenfolge, in der Ansicht ändert sich nie, was während möglich, engt ein, wie die Ansicht zeigen kann (und manipulieren) die Daten. Dies verpestet das Modell auch mit Blick Daten (Zeilenindex).

    public int RowIndexSelected { get; private set; }

    //...//

    private void gridParts_CellEnter(object sender, DataGridViewCellEventArgs e)
    {
        if (SelectedPartChangedEvent != null)
        {
            RowIndexSelected = e.RowIndex;

            SelectedPartChangedEvent();            
        }
    }

3) Eine Variation (2). Erstellen Sie ein Adapterobjekt zwischen dem Moderator und Ansicht zu sitzen. Verschieben Sie die Zeile ID Conversion-Code aus dem Modell mit dem Adapter. Der Präsentator dann übernimmt das dataGridAdapters Teil geändert Ereignis.

    public PartSelectDataGridAdapter(IPartSelectView view, PartCollection data)
    {
        _view = view;
        _data = data;

        _view.SelectedPanelChangedEvent += HandleSelectedPartChanged;
    }

    void HandleSelectedPartChanged()
    {
        int id = _data[_view.RowIndexSelected].ID;

        if (SelectedPartChanged != null)
        {
            SelectedPartChanged(id);
        }
    }

Derzeit im Lernen auf 3, da es testbar ist, hält Logik aus der Sicht und Sicht Daten aus dem Modell und Moderator.

Wie würden Sie dies angehen - gibt es eine bessere Lösung

War es hilfreich?

Lösung

Die ID ist nicht auf die angezeigt werden Benutzer und weder die Spannung ist, daher das Modell erzeugt ein Datentabelle, die nur das enthält partCode und Beschreibung.

Einfache Lösung: tun erstellen eine ID-Spalte in der Datentabelle und versteckt es in der Datagrid Ansicht .

Andere Tipps

gab ich eine einfache Lösung früher; dies ist eine detailliertere Antwort auf die Frage

Gibt es einen Grund, warum Sie wollen keinen List<Part> zur Ansicht übergeben?

Sie können das Raster konfigurieren Sie die ID und Spannung Spalte zu verbergen. Sie können einfach das ausgewählte Objekt aus der Bindungsquelle in der Ansicht bekommen. Der Präsentator kann die Ansicht für diese Auswahl Abfrage oder die Ansicht eine SelectionChanged(Part selected) auf dem Moderator anrufen können.

Es würde bedeuten, Sie sind nicht mehr streng nach den passiv-Ansicht Muster, sondern ein < a href = "http://martinfowler.com/eaaDev/SupervisingPresenter.html" rel = "nofollow"> Controller Überwachung, denn nun Ihre Ansicht über das Modell kennt.

Wenn Sie nicht so tun, können Sie eine Ansicht Modell einführen, die Sie bereits implizit tun mit Ihrem Datatable. (Dies ist nicht unbedingt schlecht, btw.)

In Ihrem Beispiel kennt die Modellklassen über die Ansicht Modelle, da Sie Methoden auf das Modell haben, die sie erzeugen. Ich würde empfehlen Ihnen, diese Beziehung zu invertieren: create-Methoden auf Ihrer Ansicht Modell, das auf den Modellobjekten abhängen. Auf diese Weise werden Sie Ihre Modellklassen schön halten und sauber und unabhängig von allen den UI-Daten in der Präsentationsschicht benötigt wird.

Bei Verwendung der View-Modell / Überwachungssteuerung Art und Weise betrachten sie das Datatable-Konzept für einfache Klassen fallen.

EDIT: Alternative, um die Ansicht völlig unwissend des Modells zu machen:

Erstellen Sie eine Instanz dieser Klasse in der Präsentator, in dem Sie die beiden Modell und View-Modell wissen:

public class PartViewModel
{
  object PartModel { get; set; }
  string Name { get; set; }
  string Description { get; set; }
}

Übergeben Sie einen List<PartViewModel> als Datenquelle an die Datagridview. Sie können das ausgewählte Objekt PartViewModel auf den Vortragenden zurückkehren (entweder ein Ereignis oder mit einem Verfahren verwendet wird). Der Moderator kennt, kann er die PartModel Eigenschaft zurück zu einem Teil Instanz gegossen. Der Blick muss nicht alles über das Modell wissen, wie Sie sagen, Sie sind bevorzugen. Aber man kann noch einfache Objektidentität im Presenter verwenden, zu vermeiden „kompliziert“ Nachschlag-IDs verwenden.

Mit einem Moderator Rückruf:

interface IPartListPresenter
{
  // other methods
  void SelectedPartChanged(PartViewModel nowSelected);
}

Unter der Annahme, partBindingSource ist die Binding der gridview verbunden ist, können Sie das Ereignis Current von partBindingSource wie folgt behandeln:

private void partBindingSource_CurrentChanged(object sender, EventArgs e)
{
  _presenter.SelectedPartChanged(partBindingSource.Current as PartViewModel);
}

In dem Moderator:

public void SelectedPartChanged(PartViewModel nowSelected)
{
  if(nowSelected == null)
  {
    return;
  }
  part myPart = (Part) nowSelected.Part;
  // dos stuff
}

Hope, das hilft.

I think you have misunderstood the whole concept a bit here!

It is the Presenter that should handle this, not the Model. The Model should only concentrate on the its sole responsibility, if not, you keep the View and Model too close!

My suggestion is to keep a hidden column in your table an pass the event of the selected row to your Presenter, and then let the Presenter handle to the work!

This will be the correct usage of MVP.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top