我已经使用被动视图模式实现了MVP三元组-即视图仅包含简单的getter和setter.但是,我很难分离视图数据和模型数据.特别是在处理视图状态更改时.
三重轴用于使用户能够从列表中选择零件.零件清单由模型提供,每个零件均由唯一的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分配给视图上的属性,该视图映射到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;
}
}
}
到现在为止还挺好.该视图在DataGridView中分配过滤后的数据.
我遇到的问题是退还用户选择的零件.
该视图不知道唯一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是可测试的,因此我正在学习3,将逻辑置于视图之外,并将数据置于模型和演示者之外.
您将如何解决-是否有更好的解决方案?
解决方法:
The ID is not to be displayed to the
user and neither is the voltage,
therefore the model creates a
DataTable that contains just the
partCode and description.
一个简单的解决方案:在数据表和hide it in in the datagrid view中创建一个ID列.