パッシブ ビュー パターンを使用して MVP トライアドを実装しました。つまり、ビューには単純なゲッターとセッターしか含まれていません。ただし、ビュー データとモデル データの分離に問題があります。特に、ビューステートの変更を処理する場合。
トライアドは、ユーザーがリストからパーツを選択できるようにするために使用されます。パーツのリストはモデルによって提供され、各パーツは一意の ID によって一意に識別されます。
パーツが次のようになっているとします。
class Part
{
int ID; // this code uniquely identifies the part within the model
String partCode;
String description;
double voltage;
}
ビューはユーザーにリストを表示し、パーツを選択できるようにします
リストは DataGridView に表示され、パーツは dataGridView の行をクリックして選択されます。
ID はユーザーに表示されず、電圧も表示されないため、モデルは partCode と説明のみを含む DataTable を作成します。この DataTable は、プレゼンターによって、DataGridView の DataSource プロパティにマップされるビューのプロパティに割り当てられます。
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;
}
}
}
ここまでは順調ですね。View は、フィルター処理されたデータを DataGridView に表示します。
私が抱えている問題は、ユーザーが選択した部分を返すことです。
一意の ID は表示されず、他の情報が一意であることを保証できないため、ビューは一意の ID を認識しません。したがって、選択されたパーツを一意に識別することはできません。
基本的に、他のデータを使用するコンポーネントを使用せずに、ビュー データ (選択した行) をモデル データ (選択した部分) に変換しようとしています。
これまでのところ、次の解決策があります。
1) ID を含む DataTable がビューに渡され、表示がユーザーに表示されないようにフィルター処理されます。選択した行の ID を返すのは簡単です。ここでの問題は、テストされていないロジック (ディスプレイのフィルタリング) でビューを汚染してしまったことです。
2) ビューは行インデックスを返し、モデルはこのインデックスを元のデータの行と照合します。これは、ビュー内の順序が決して変更されないようにすることを意味します。これは可能ではありますが、ビューがデータを表示 (および操作) する方法を制限します。これはまた、モデルをビュー データ (行インデックス) で汚染します。
public int RowIndexSelected { get; private set; }
//...//
private void gridParts_CellEnter(object sender, DataGridViewCellEventArgs e)
{
if (SelectedPartChangedEvent != null)
{
RowIndexSelected = e.RowIndex;
SelectedPartChangedEvent();
}
}
3) (2) のバリエーション。プレゼンターとビューの間に配置するアダプター オブジェクトを作成します。行から ID への変換コードをモデルからアダプターに移動します。次に、プレゼンターは dataGridAdapters パーツの変更イベントを処理します。
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);
}
}
現在、テスト可能であるため、3に向けて学習しており、ロジックをビューから除外し、データをモデルとプレゼンターから除外しています。
これにどのように取り組みますか - より良い解決策はありますか?