在教程的第四部分(http://www.blogjava.net/usherlight/archive/2009/06/20/283396.html)我們已經粗略地介紹了Tapestry的前綴,其中提及最常用的兩種literal和prop。這裏順便再介紹一下其他的幾個前綴.
1、context,這個經常在引用圖片的時候用到。比如:<img src="${context:images/icon.png}"/> 這樣就能夠在頁面上顯示在web-inf/images/icon.png
2、message,這個是需要I18N的應用必用的前綴。${message:some-key}
3、var,用於定義生成一個臨時變量。比如:<li t:type="loop" source="1..10" value="var:index">${var:index}</li>。如果沒有加這個前綴var:的話,就需要在頁面類中添加一個property: index以及相應的getter和setter。
我們這次介紹自定義一個cycle前綴,這個可以用於在表格中顯示不同背景的行(也就是斑馬條)。
比如:
<t:grid .... rowClass="cycle:line1,line2">
...
</t:grid>
或者
<t:loop ...>
<div class="${cycle:line1,line2}">aaaa</div>
</tloop>
自定義prefix一般來說是3個步驟,
1、定義一個BindingFactory,這個需要實現BindingFactory接口
2、定義一個Binding繼承AbstractBinding
3、註冊這個Binding
看一下具體的prefix的類:
2import java.util.List;
3
4import org.apache.tapestry5.Binding;
5import org.apache.tapestry5.BindingConstants;
6import org.apache.tapestry5.ComponentResources;
7import org.apache.tapestry5.ioc.Location;
8import org.apache.tapestry5.services.BindingFactory;
9import org.apache.tapestry5.services.BindingSource;
10
11/**
12 * Implementation of the cycle: binding prefix -- we parse list of bindings
13 * and generate delegate bindings for each element<br>
14 * default binding is literal, other bindings can be used by specifying prefix.<br>
15 * example: "cycle:prop:name,prop:lastName,sth,sth else"
16 */
17public class CycleBindingFactory implements BindingFactory {
18 private final BindingSource _bindingSource;
19
20 public CycleBindingFactory(BindingSource source){
21 this._bindingSource = source;
22 }
23
24 public Binding newBinding(String description, ComponentResources container, ComponentResources component,
25 String expression, Location location)
26 {
27 List<Binding> delegates = new ArrayList<Binding>();
28 String[] bindingNames = expression.split(",");
29
30 for (String bindingName : bindingNames){
31 String defaultBinding = BindingConstants.LITERAL;
32
33 Binding binding = _bindingSource.newBinding(description, container, component, defaultBinding, bindingName, location);
34 delegates.add(binding);
35 }
36
37 CycleBinding cycleBinding = new CycleBinding(delegates);
38 container.addPageLifecycleListener(cycleBinding);
39
40 return cycleBinding;
41 }
42}
2
3import org.apache.tapestry5.Binding;
4import org.apache.tapestry5.internal.bindings.AbstractBinding;
5import org.apache.tapestry5.runtime.PageLifecycleListener;
6
7
8public class CycleBinding extends AbstractBinding implements PageLifecycleListener{
9 private final List<Binding> delegates;
10 private int index = 0;
11
12 public CycleBinding(List<Binding> delegates) {
13 this.delegates = delegates;
14 }
15
16 public Object get() {
17 Object ret = delegates.get(index).get();
18 index ++;
19 if(index>=delegates.size()) index = 0;
20 return ret;
21 }
22
23 @Override
24 public boolean isInvariant() {
25 return false;
26 }
27
28 @Override
29 public Class<Object> getBindingType() {
30 return Object.class;
31 }
32
33
34 public void containingPageDidDetach() {
35 index=0;
36 }
37
38 public void containingPageDidAttach() {/*not interested*/}
39
40 public void containingPageDidLoad() {/*not interested*/}
41}
Binding和BindingFactory寫好了,註冊後就可以使用了,註冊的過程是在AppModel中添加以下一段代碼:
2 MappedConfiguration<String, BindingFactory> configuration,
3 BindingSource bindingSource
4 )
5 {
6 configuration.add("cycle",new CycleBindingFactory(bindingSource));
7 }