我有一个问题,我试图在Image中解释。我希望这将有助于所有人理解我需要的东西。
My Base Page就像这样(menuNavPanel是树面板):
<div class="colContainer">
<div class="leftColumn" >
<div wicket:id="menuNavPanel"></div>
</div>
<div class="rightColumn">
<wicket:child/>
</div>
</div>
作为Base Page的孩子的Ny BIA Page是这样的:
<wicket:extend>
<div wicket:id="bodyPanel"></div>
</wicket:extend>
在我的树面板中,当我点击一个节点时代码为:
@Override
protected void onNodeLinkClicked(AjaxRequestTarget target, TreeNode node) {
super.onNodeLinkClicked(target, node);
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)node;
Unit unitObject =(Unit) treeNode.getUserObject();
// I want to call bodyPanel fo child page passing the unitObject param
}
现在,如何调用子页面的bodyPanel从父页面的树面板传递unitObject参数?
我能表达我的问题吗?希望得到一些帮助:)
答案 0 :(得分:4)
不是执行覆盖方法,而是升级到Wicket 1.5并使用新的event bus在组件之间进行通信。您可以创建特定于组件用例的自定义类型安全事件:例如“ItemAddedToShoppingCart”或“GlobalThermoNuclearWarStarted”。
linked article in the 1.5 migration guide提供了有关如何设置内容的足够信息。
答案 1 :(得分:3)
我不确定我是否正确理解了问题。您的BasePage
使用TreePanel
定义了一个左列,并允许子类在右列div中展开。您通常会在BodyPanel
的子类中放置BasePages
。现在,您想要在BodyPanel
上的某个事件上调用TreePanel
的方法。
您可以在BasePage上使用可覆盖的方法来执行此操作,该方法将在TreePanel
到getPage()
中调用。您的子页面将覆盖该方法,其实现将调用它们持有的BodyPanel
。
public class BasePage ... {
// Hook
public void treePanelSelected(Object someObject) { }
...
}
public class ChildPage extends BasePage ... {
BodyPanel bodyPanel;
@Override
public void treePanelSelected(Object someObject) {
bodyPanel.selectionChanged/(someObject);
}
...
}
public class TreePanel ... {
...
@Override
protected void onNodeLinkClicked(AjaxRequestTarget target, TreeNode node) {
super.onNodeLinkClicked(target, node);
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)node;
Unit unitObject =(Unit) treeNode.getUserObject();
((BasePage)getPage()).treePanelSelected(unitObject);
}
}
由于我对你的具体需求和实现细节的无知,我不明白为什么需要继承子页面。您可以在BasePage中添加BodyPanel
并从同一个类控制它。
答案 2 :(得分:2)
谢谢大家,在回顾了所有不错的选项后,我终于选择了由martijn定义的事件总线方式。我所做的是创建了一个事件有效负载并连接了面板以进行通话。我还需要将选定的Id /实体传递给接收面板。
有没有办法根据树元素的模型设置接收面板的复合属性模型,这样我就不需要手动做模型了?
我暂时这样做了:
public class TreeNodeClickUpdate {
private final AjaxRequestTarget target;
private final long selectedId;
/**
* Constructor
*
* @param target
* @param selectedId
*/
public TreeNodeClickUpdate(AjaxRequestTarget target, long selectedId)
{
this.target = target;
this.selectedId = selectedId;
}
/** @return ajax request target */
public AjaxRequestTarget getTarget()
{
return target;
}
public long getSelectedId() {
return selectedId;
}
}
在发件人方面,我这样做了:
send(getPage(), Broadcast.BREADTH,
new TreeNodeClickUpdate(target, unitObject.getId()));
在接收端我得到了这样的话:
@Override
public void onEvent(IEvent<?> event) {
super.onEvent(event);
if (event.getPayload() instanceof TreeNodeClickUpdate)
{
TreeNodeClickUpdate update = (TreeNodeClickUpdate)event.getPayload();
setSelectedId(update.getSelectedId()); //sets to id field of panel
update.getTarget().add(this);
}
}
并且仅作为我的接收面板中的示例,为了获得我创建了这样的标签的值:
label = new Label("label",new PropertyModel<BiaHomePanel>(this,"selectedId"));
后来,实际上我想从实体获取信息并以表格形式显示。是否有更好的方式以更好的方式传递模型,或者我应该作为事件有效负载中的参数传递。
答案 3 :(得分:1)
有两种方法可以做到这一点。一个更干净,但需要更多代码。另一个很快又脏。
方法1 :(好)
由于您的父页面正在扩展,您可以在父级中提供一个抽象方法,如
protected abstract WebMarkupContainer getBodyPanel();
在您的子页面中实现并返回相应的面板。然后,您可以从父页面的面板中调用该方法。这类似于其他用户建议的可重写方法。
方法2 :(差)
Wicket组件层次结构在父页面和子页面之间共享。因此,如果您确保bodyPanel具有唯一的wicketId并直接添加到页面的根目录,则可以直接调用
get("bodyPanelId");
它将返回正确的面板。
答案 4 :(得分:1)
当我遇到问题时,我想到了解决这个问题的两种方法(1.5之前):
a)实现观察者模式的变体,以通知其他组成部分,例如:Realising complex cross-component ajax actions in wicket - The observer way
b)使用wicket访问者遍历组件树。
我决定选择变体a)但是这会引入从组件到页面实现的耦合,这会导致在自己测试面板时出现问题。所以也许b)可能是更好的主意,但由于我的应用程序运行得相当顺利,a)已实现,下一个重要步骤将切换到1.5和事件总线,我还没有尝试过b)。