组件:grid
,columns
,column
,rows
和 row
。
Grid包含排列整齐的组件就像表格一样。在grid内,你可以声明columns,定义了header及column属性;还可以声明 rows,提供内容。
使用rows组件可以声明一套row,即为grid元素的子组件。在rows内可以为每一行添加row组件。你可以 在row元素内添加你想要的内容。每个子元素为指定行的一列。
类似的,columns是由columns
组件声明的,其将作为grid的一个子组件。不同于row用于保留每行的内容,column声明了每列的通用属性,例如宽度和对齐方式,还有可选的headers,也就是标签或图像。
<grid> <columns> <column label="Type"/> <column label="Content"/> </columns> <rows> <row> <label value="File:"/> <textbox width="99%"/> </row> <row> <label value="Type:"/> <hbox> <listbox rows="1" mold="select"> <listitem label="Java Files,(*.java)"/> <listitem label="All Files,(*.*)"/> </listbox> <button label="Browse..."/> </hbox> </row> </rows> </grid>
当指定了height
属性且没有足够的空间来显示数据时,grid会变为滚动的。
<grid width="500px" height="130px"> <columns> <column label="Head 1"/> <column label="Head 2" align="center"/> <column label="Head 3" align="right"/> </columns> <rows> <row> <listbox mold="select"> <listitem label="Faster"/> <listitem label="Fast"/> <listitem label="Average"/> </listbox> <datebox/> <textbox rows="2"/> </row> <row> <checkbox checked="true" label="Option 1"/> <checkbox label="Option 2"/> <radiogroup> <radio label="Apple"/> <radio label="Orange" checked="true"/> <radio label="Lemon"/> </radiogroup> </row> <row> <checkbox checked="true" label="Option 1"/> <checkbox label="Option 2"/> <radiogroup orient="vertical"> <radio label="Apple"/> <radio label="Orange" checked="true"/> <radio label="Lemon"/> </radiogroup> </row> </rows></grid>
如果你允许用户改变每列的宽度,可以将columns
的sizable
属性的设为true
。一旦允许用户进行此操作,用户可以通过拖动相邻列的边框来改变列宽,如下,
<window> <grid> <columns id="cs" sizable="true"> <column label="AA"/> <column label="BB"/> <column label="CC"/> </columns> <rows> <row> <label value="AA01"/> <label value="BB01"/> <label value="CC01"/> </row> <row> <label value="AA01"/> <label value="BB01"/> <label value="CC01"/> </row> <row> <label value="AA01"/> <label value="BB01"/> <label value="CC01"/> </row> </rows> </grid> <checkbox label="sizeable" checked="true" onCheck="cs.sizeable = self.checked"/> </window>
有两种方式在grid中处理较长的内容:滚动及分页。滚动可以由指定height
属性来实现,就像在前面讨论的一样。分页可以通过将mold
属性设为paging
来实现的。一旦分页可用,grid会将内容分为几页并且在同一时间内只显示一页。如下所示,
<grid width="300px" mold="paging" pageSize="4"> <columns> <column label="Left"/> <column label="Right"/> </columns> <rows> <row> <label value="Item 1.1"/><label value="Item 1.2"/> </row> <row> <label value="Item 2.1"/><label value="Item 2.2"/> </row> <row> <label value="Item 3.1"/><label value="Item 3.2"/> </row> <row> <label value="Item 4.1"/><label value="Item 4.2"/> </row> <row> <label value="Item 5.1"/><label value="Item 5.2"/> </row> <row> <label value="Item 6.1"/><label value="Item 6.2"/> </row> <row> <label value="Item 7.1"/><label value="Item 7.2"/> </row> </rows> </grid>
一旦设置为分页模式,grid将会创建paging
组件的一个实例作为其子组件。然后它将会关注分页( It then takes care of paging for the grid it belongs to)。
如果你喜欢将paging
组件置于不同的位置或你想使用同一个paging
组件控制两个或更多的grid,可以明确指明paginal
属性。注意:如果没有明确指明,即同于paging
属性。
<vbox> <paging id="pg" pageSize="4"/> <hbox> <grid width="300px" mold="paging" paginal="${pg}"> <columns> <column label="Left"/><column label="Right"/> </columns> <rows> <row> <label value="Item 1.1"/><label value="Item 1.2"/> </row> <row> <label value="Item 2.1"/><label value="Item 2.2"/> </row> <row> <label value="Item 3.1"/><label value="Item 3.2"/> </row> <row> <label value="Item 4.1"/><label value="Item 4.2"/> </row> <row> <label value="Item 5.1"/><label value="Item 5.2"/> </row> <row> <label value="Item 6.1"/><label value="Item 6.2"/> </row> <row> <label value="Item 7.1"/><label value="Item 7.2"/> </row> </rows> </grid> <grid width="300px" mold="paging" paginal="${pg}"> <columns> <column label="Left"/><column label="Right"/> </columns> <rows> <row> <label value="Item A.1"/><label value="Item A.2"/> </row> <row> <label value="Item B.1"/><label value="Item B.2"/> </row> <row> <label value="Item C.1"/><label value="Item C.2"/> </row> <row> <label value="Item D.1"/><label value="Item D.2"/> </row> <row> <label value="Item E.1"/><label value="Item E.2"/> </row> <row> <label value="Item F.1"/><label value="Item F.2"/> </row> </rows> </grid> </hbox></vbox>
grid支持直接的行排序。如果你想打开某一列的递增排序,可以为sortAscending
属性指派一个java.util.Comparator
实例。类似的,可以为sortDescending
属性指派一个comparator来打开递减排序。
如下所示,首先得实现comparator 接口来比较grid的任意两行,然后将其实例指派给sortAscending
和sortDescending
属性。注意:compare
方法由org.zkoss.zul.Row
的实例调用。
<zk> <zscript> class MyRowComparator implements Comparator { public MyRowComparator(boolean ascending) { ... } public int compare(Object o1, Object o2) { Row r1 = (Row)o1, r2 = (Row)o2; .... } } Comparator asc = new MyRowComparator(true); Comparator dsc = new MyRowComparator(false); </zscript> <grid> <columns> <column sortAscending="${asc}" sortDescending="${dsc}"/> ...
sortDirection
属性用来控制是否在客户端显示一个图标,以显示特定列的排列顺序。如果每行元素在添加到grid前即已排好序,则需要明确设定这个属性。
<column sortDirection="ascending"/>
然后,只要你为相应的列指定比较器(comparator),grid会自动维护此属性。
当你为某一列至少指定了一个比较器(comparator),则若用户点击了此列onSort
事件会被送至服务器。column
组件实现了监听器,基于指定的比较器(comparator)自动为行(rows)排序。
若你倾向于手工处理,可以为onSort
事件将你自己的监听器添加到指定列。为了阻止默认的监听器调用sort
方法,你必须调用stopPropagation
方法来阻止事件被接收。另外,你可以重定义sort
方法,见下文。
sort
方法是onSort
事件监听器的最底层实现。如果你使用Java代码为行排序,则这会非常有用。例如,你或许必须在添加行(假定未排序)后调用此方法。
Row row = new Row(); row.setParent(rows); row.appendChild(...); ... if (!"natural".column.getSortDirection()) column.sort("ascending".equals(column.getSortDirection()));
默认排序算法为快速排序(quick-sort)(org.zkoss.zk.ui.Components
类的sort
方法)。你可以使用自己的实现来重定义此方法。
注:sort
方法会检测排序顺序(通过调用getSortDirection
)。仅在排序顺序不同时sort才会为行排序。若想强制排序,可按如下方式,
column.setSortDirection("natural"); sort(myorder);
等价于:
sort(myorder, true);
就像listbox,gird支持live data一样。使用实况数据,开发人员可以将数据从视图分离。换言之,开发人员仅需实现rg.zkoss.zul.ListMode
l接口类提供数据。而非直接操作grid。好处有以下两点,
易于使用不同的视图来显示相同的数据。
grid仅在其可见时才会将数据送至客户端。在数据量巨大时可以减少大量的网络流量(network traffic)。
使用实况数据需要经过三步,
以ListModel
形式准备好数据。ZK有一个称为org.zkoss.zul.SimpleListModel
的具体实现,用于显示一个数组对象。
实现org.zkoss.zul.RowRenderer
接口用于将数据行送至grid。
这是可选的。若为指定,默认的渲染器(renderer)会启,并将数据送至第一列。
你可以实现不同的渲染器(renderer),这样可以在不同的视图中显示相同的数据。
在model属性中指定数据,并且可以选择在rowRenderer
属性指定渲染器(renderer)。
在下面的例子中,我们准备了一个称为strset
的列表模型,通过grid的model
属性为其指定此值。然后,grid会处理剩下的工作。
<window title="Live Grid" border="normal"> <zscript> String[] data = new String[30]; for(int j=0; j < data.length; ++j) { data[j] = "option "+j; } ListModel strset = new SimpleListModel(data); </zscript> <grid width="100px" height="100px" model="${strset}"> <columns> <column label="options"/> </columns> </grid></window>
如果你允许用户为提供实况数据的grid排序,则必须要实现org.zkoss.zul.ListModel
及org.zkoss.zul.ListModelExt
接口。
class MyListModel implements ListModel, ListModelExt { public void sort(Comparator cmpr, boolean ascending) { //do the real sorting //notify the grid (or listbox) that data is changed by use of ListDataEvent } }
当用户请求grid排序时,grid将会调的用ListModelExt
的sort
方法来为数据排序。换言之,排序 是由列表模型(list mode)完成的,而不是grid。
排序完成之后,列表模型会调用org.zkoss.zul.event.ListDataListener
实例(通过addListDataListener
方法注册在grid)的onChange
方法来通知grid。在大多数情况下,所有的数据通常会变化,所以列表模型通常会发送下列事件:
new ListDataEvent(this, ListDataEvent.CONTENTS_CHANGED, -1, -1)
除了columns,你可以使用auxhead
和auxheader
组件指定辅助表头,如下。
<grid> <auxhead> <auxheader label="H1'07" colspan="6"/> <auxheader label="H2'07" colspan="6"/> </auxhead> <auxhead> <auxheader label="Q1" colspan="3"/> <auxheader label="Q2" colspan="3"/> <auxheader label="Q3" colspan="3"/> <auxheader label="Q4" colspan="3"/> </auxhead> <columns> <column label="Jan"/><column label="Feb"/><column label="Mar"/> <column label="Apr"/><column label="May"/><column label="Jun"/> <column label="Jul"/><column label="Aug"/><column label="Sep"/> <column label="Oct"/><column label="Nov"/><column label="Dec"/> </columns> <rows> <row> <label value="1,000"/><label value="1,100"/><label value="1,200"/> <label value="1,300"/><label value="1,400"/><label value="1,500"/> <label value="1,600"/><label value="1,700"/><label value="1,800"/> <label value="1,900"/><label value="2,000"/><label value="2,100"/> </row> </rows> </grid>
辅助表头支持colspan
和rowsspan
属性,而列表头(column header)并不支持。但是,就像名字暗示的那样,辅助表头必须和column
一起使用。
不同于column/columns
仅可以为grid所使用,auhead/auxheader
可以被用于grid,listbox 和 tree
。
为一个整数列表,以逗号分隔,用于就控制是否将一个元素(cell)跨越几列。列表中的第一个数字表示第一个元素跨越的列数,第二个数字表示第二个元素跨越的列数,依次类推。若省略数字,则为1。
例如,
<grid> <columns> <column label="Left" align="left"/><column label="Center" align="center"/> <column label="Right" align="right"/><column label="Column 4"/> <column label="Column 5"/><column label="Column 6"/> </columns> <rows> <row> <label value="Item A.1"/><label value="Item A.2"/> <label value="Item A.3"/><label value="Item A.4"/> <label value="Item A.5"/><label value="Item A.6"/> </row> <row spans="1,2,2"> <label value="Item B.1"/><label value="Item B.2"/> <label value="Item B.4"/><label value="Item B.6"/> </row> <row spans="3"> <label value="Item C.1"/><label value="Item C.4"/> <label value="Item C.5"/><label value="Item C.6"/> </row> <row spans=",,2,2"> <label value="Item D.1"/><label value="Item D.2"/> label value="Item D.3"/><label value="Item D.5"/> </row> </rows> </grid>