Wicket黑客使用ListView,哪些替代方案?



Wicket使用模型可能很麻烦。为了使有状态页面正确呈现对象,您需要使用大量样板代码,覆盖类以正确获取可见性状态等......一个简单的例子:

private IModel<FooBar> fooBarModel;
public MyPage() {
Label lbl1 = new Label("field1",
new PropertyModel<>(fooBarModel, "field1")) {
@Override public boolean isVisible() {
return fooBarModel.getObject().someCondition();
}   }
add(lbl1);
/// Etc... same for dozen of other fields
}

我经常使用一个技巧,使用ListView来提供帮助。同样的例子:

public MyPage() {
add(new ListView<FooBar>("content",
new SingleListModel<FooBar>(fooBarModel)) {
@Override protected void populateItem(...) {
FooBar fooBar = item.getModelObject();
// Code here gets simpler:
Label lbl1 = new Label("field1", fooBar.getField1());
lbl1.setVisible(fooBar.someCondition());
item.add(lbl1);
// Etc...
}
});
}

使用一个简单的实用程序类SingleListModel,它将IModel<T>转换为ListModel<T>,具有 1 或 0 个元素,具体取决于 T 是否为空:

public class SingleListModel<T>
extends LoadableDetachableModel<List<T>> {
private IModel<T> tModel;
public SingleListModel(IModel<T> tModel) {
this.tModel = tModel;
}
@Override
protected List<T> load() {
List<T> ret = new ArrayList<>(1);
T t = tModel.getObject();
if (t != null)
ret.add(tModel.getObject());
return ret;
}
}

这样做的副作用是,如果fooBarModel返回null,标记中的整个"content"元素都是隐藏的;不需要特殊处理。

但这一切对我来说都像是一种黑客攻击,因为我以一种"不自然"的方式使用ListView

有没有更干净的方法来获得相同的结果?标准的检票口框架?

您应该改用行为以避免此类重复。

public class MyBehavior extends Behavior {
private final MyModel model;
public MyBehavior(MyModel model) {this.model = model;}
@Override public void onConfigure(Component c) {
if (model.someCondition()) {
component.setVisible(false);
}
}
}

用法:

MyBehavior b = new MyBehavior(modelInstance);
component1.add(b);
component2.add(b);
// dozen more
Label lbl1 = new Label("field1",
new PropertyModel<>(fooBarModel, "field1")) {
@Override public boolean isVisible() {
return fooBarModel.getObject().someCondition();
}   }
add(lbl1);

只需很少的重构,它就可以转换为

add(new FLabel("id","text")
.setVisibilityFunction(()->model.getObject().isVisible()))
);

弗拉贝尔类:

public class FLabel extends Label implements IComponentWithVisibilityFunction<FLabel> {
private SerializableBooleanSupplier visibilityFunction;
public FLabel(String id) {
super(id);
}
public FLabel(String id, Serializable label) {
super(id, label);
}
public FLabel(String id, IModel<?> model) {
super(id, model);
}
@Override
public FLabel setVisibilityFunction(SerializableBooleanSupplier visibilityFunction) {
this.visibilityFunction = visibilityFunction;
return this;
}
@Override
protected void onConfigure() {
if (visibilityFunction != null) {
setVisible(visibilityFunction.getAsBoolean());
}
}
}
public interface IComponentWithVisibilityFunction<T> {
T setVisibilityFunction(SerializableBooleanSupplier visibilityFunction);
}

此外,您可以将供应商放入构造函数中:

add(new FLabel("id","text", ()->model.getObject().isVisible()));

最新更新