想象一下,我有一个班级CellTreeWidget
,其中包含CellTree
。
我想写一个与
交互的演示者CellTreeWidget
实例和 CellTreeWidget
中显示的数据是项目列表。每个项目都有一个父项目,属于一个容器。
public class Container
{
public List<Item> getItemList();
public void setItemList(List<Item> aItemList);
}
public class Item
{
public int getItemId();
public int getParentItemId();
}
以下过程涉及演示者:
Presenter.startEdit
)。Presenter.save
)。当用户选择容器时,必须更新CellTreeWidget
以显示新选择的容器的项目。
当用户保存对容器所做的更改时,演示者必须
步骤2是必要的,因为用户可以在客户端上创建新项目。当它们保存在服务器上时,它们的数据(主键)会发生变化。
为了实现这一点,我被告知使用以下方法:
public class Presenter
{
private RemoteService service;
private View view;
private ListDataProvider<Item> dataProvider;
private Container data;
public Presenter()
{
dataProvider = new ListDataProvider<Item>(new ItemProvidesKey());
}
public void setService(final RemoteService aService)
{
service = aService;
}
public void setView(final View aView)
{
view = aView;
final HasData<Item> dataToDisplay = view.getDisplay();
if (dataToDisplay != null)
{
dataProvider.addDataDisplay(dataToDisplay);
}
}
public void save() {
List<Item> allPages = new ArrayList<Item>();
allPages.addAll(dataProvider.getList());
data.setItemList(allPages);
service.save(data, new AsyncCallback<ContainerSaveResult>() {
@Override
public void onSuccess(ContainerSaveResult result) {
afterSave(result);
}
@Override
public void onFailure(Throwable caught) {
Window.alert("Save error: " + caught.getMessage());
}
});
}
protected void afterSave(ContainerSaveResult result)
{
for (final Page curItem : dataProvider.getList())
{
final Integer oldId = curPage.getItemId();
final Integer newId = result.getNewItemIdsByOldItemIds().get(oldId);
if (newId != null)
{
curPage.setItemId(newId);
}
}
dataProvider.flush();
}
public void startEdit(Container aContainer)
{
data = aContainer;
if (data != null)
{
view.getDisplay().setRowCount(data.getItemList().size(), true);
dataProvider.setList(data.getItemList());
}
}
}
CellTreeWidget
实现了接口View
,其定义如下:
public interface View extends IsWidget, HasSelectionChangedHandlers {
HasData<Item> getDisplay();
}
这种方法的问题在于,我认为没有明显的方法可以在HasData<Item> getDisplay()
类中提供方法CellTreeWidget
的实现。
因此我的问题是:如果你
CellTree
,并希望实现一个更新数据和视图的干净机制,如何以正确的GWT风格方式完成?
答案 0 :(得分:2)
令人遗憾CellTree
是一个非常复杂的小部件,与CellTable
或DataGrid
相比,使用的概念完全不同。
这也是它不像其他CellWidgets那样阻止HasData
接口的原因。
此外,CellTree
更新和刷新其节点并不是很好的支持。有几种解决方法(请参阅here和here)。
试图解决其中一些问题的CellTree
也有扩展(Project,Code,Demo)。
我建议首先使用CellTree
实现您的用例,然后担心它是否符合MVP
样式。我已经可以告诉你,在处理View
时,在Presenter
和CellTree
之间绘制清晰的边界并不容易。
如果我正确理解了您的用例,那么您有Container
个对象列表(您使用的是CellList
吗?),当您选择特定容器时,您想要显示项目列表在CellTree
中,允许用户编辑和添加/删除项目。
我将尝试强调重要的步骤:
1。)您的数据结构与CellTree
不能很好地协同工作。您应该引用父项和每个项目中的子项列表:
public class Item
{
public int getItemId();
public Item getParent();
public List<Item> getChilds();
}
与CellTree
或DataGrid
不同的 CellTable
使用TreeViewModel
。
2.。)定义自定义TreeViewModel
。
public class MyCustomTreeModel implements TreeViewModel {
private final SelectionModel<Item> selectionModel;
private final ValueUpdater<Item> valueUpdater;
public MyCustomTreeModel(final SelectionModel<Item> selectionModel, ValueUpdater<Item> valueUpdater) {
this.selectionModel = selectionModel;
this.valueUpdater = valueUpdater;
}
@Override
public <T> NodeInfo<?> getNodeInfo(final T value) {
// The root node is the container
ListDataProvider<Item> = new ListDataProvider<Item>();
if (value instanceof Container) {
provider.setList(((Container)value).getItemList();
return new DefaultNodeInfo<Item>(provider, containerCell, selectionModel,null);
}
provider.setList(((Item)value).getChilds());
return new DefaultNodeInfo<Item>(provider, itemCell, selectionModel, valueUpdater);
}
@Override
public boolean isLeaf(Object value) {
Item item = (Item) value;
return value != null && item.getChild().size() == 0;
}
}
3.。)在MyCustomTreeModel
中实例化自定义View
并使用所选的CellTree
实例创建Container
(您可以在Presenter
时创建public void onStartEdit(Container container, SelectionModel<Item> selectionModel, ValueUpdater<Item> valueUpdater) {
CellTree tee = new CellTree(new MyCustomTreeModel(selectionModel,valueUpdater));
}
你选择一个容器:
add()
同样,您可能会遇到令人耳目一新的问题,您必须在remove()
添加TreeViewModel
和CellTree
功能才能添加和删除项目。
查看一些变通方法和代码的链接问题,我建议使用扩展的{{1}}。如果可能,请使用其他Widget。