基本说明
DataGrid的基本属性和使用方法与Grid一致,本文不再做详细说明,详情请参考:Grid(DCUG)
与Grid最大的不同是:Grid通过items属性定义内部的数据行,而DataGrid通过其所设定的DataSet和DataPath属性所计算得到的EntityList作为自身的数据行。
另外由于DataSet的数据绑定效果,如果我们希望调整DataGrid中的数据,只要直接修改DataSet中的数据,DataSet会自动通知所绑定的DataGrid刷新内部数据行。
详细属性说明
autoCreateColumns
是否自动根据绑定的Entity的DataType自动创建其中的表格列。
如下图虽然我们未在DataGrid中定义与DataType相关的DataColumn:
但是由于设置了autoCreateColumns属性为true,则在运行时,会自动根据关联的Entity对象的DataType创建DataColumn,效果如下:
filterMode
在Grid中我们详细介绍过Grid的过滤栏的功能。如果设置Grid的showFilterBar为true后就可以在Grid中看到过滤栏:
由于Grid中的数据都是定义在items属性中的,因此其过滤工作也是在客户端完成的,也就是说只能对客户端的数据做过滤。
DataGrid通常情况下可能会有分页处理,如果仅仅是客户端的过滤可能并不是客户所需要的功能,在更多的业务场景中用户可能更希望你是一个数据库的查询过滤。
因此DataGrid提供了filterMode属性:
它支持两种过滤查询:clientSide和serverSide。
其中clientSide与Grid的过滤栏查询一样,就是基于Grid中当前可见记录的查询。
如果设置为serverSide查询,那么过滤栏中的查询条件将会被传递到服务器的DataProvider中,由DataProvider处理查询参数Criteria。
参数criteria对应的Java类为:com.bstek.dorado.data.provider.Criteria.java。
@DataProvider public void getAll(Page<Order> page, Criteria criteria) throws Exception { if (null!=criteria && criteria.getCriterions().size()>0){ List<Criterion> criterions = criteria.getCriterions(); for(Criterion criterion: criterions){ if (criterion instanceof SingleValueFilterCriterion){ SingleValueFilterCriterion filterCriterion = (SingleValueFilterCriterion)criterion; String property = filterCriterion.getProperty();//要查询的属性 String value = (String)filterCriterion.getValue();//查询属性值 } } //TODO,根据上面客户端传过来的查询条件,查询数据库并返回查询结果 } }
详细说明参考Java-API或Criteria对象使用说明
sortMode
在Grid或DataGrid中单击页眉中的列标题,Grid会自动根据当前列数据的大小正序或反序排列,如下图:
ID正序排列(注意id标题栏中的小三角图标):
ID反序排列(注意id标题栏中的小三角图标):
默认情况下这种排序机制是在客户端完成的,是基于客户端已有的数据所做的排序处理。
在分批数据下载机制下,如分页等,如果我们希望对所有的数据做排序处理,那么就需要设定DataGrid的sorgMode属性为serverSide:
采用serverSide的排序模式后,其排序机制的实现就要有Java后台完成了。在定义DataProvider代码的时候要声明com.bstek.dorado.data.provider.Criteria参数,相关排序的详细信息都包含在其中:
@DataProvider public void getAll(Page<Order> page, Criteria criteria) throws Exception { if (null!=criteria && criteria.getOrders().size()>0){ com.bstek.dorado.data.provider.Order propertyOrder = criteria.getOrders().get(0); String property = propertyOrder.getProperty();//要排序的属性 boolean isDesc = propertyOrder.isDesc();//正序还是反序 //TODO,根据上面客户端传过来的排序设置,查询数据库并返回查询结果 } }
上面的逻辑中你只要实现TODO中的代码就能实现一个serverSide的排序功能。
另外如果你是采用Hibernate中面向对象的开发模式,那还可以考虑使用Hibernate-addon中的工具类HibernateUtils实现:
@DataProvider public void getAll(Page<Order> page, Criteria criteria) throws Exception { DetachedCriteria detachedCriteria = DetachedCriteria .forClass(Order.class); if (criteria != null) { orderDao.find(page, HibernateUtils.createFilter(detachedCriteria, criteria)); } else { orderDao.find(page); } }
HibernateUtils工具类会自动的将com.bstek.dorado.data.provider.Criteria参数转换为Hibernate中的org.hibernate.criterion.DetachedCriteria对象,简化代码的编写。
常用技巧
onRenderCell
通常我们都是利用DataColumn的onRenderCell实现单元格的渲染控制,如果我们想自定义单元格中的信息,如:显示超链接,显示图片,显示按钮,多个DataColumn中的值合并显示等等,这些都是通过onRenderCell事件实现的,并且其中最常用的一个js方法为xCreate,
下面我们列举其中的几种常见的场景(关于xCreate更详细的说明请参考client-api中的文档):
参考文档(自定义渲染的表格(sample-center))
表格超链接
效果如下:
实现办法
找到对应的DataColumn的onRenderCell事件:
其中编写代码:
jQuery(arg.dom).empty(); jQuery(arg.dom).xCreate({ tagName: "A", href: "#", content: arg.data.get("shipCountry"), onclick: function() { alert(arg.data.get("shipCountry")); } });
如果希望有多个链接,可以通过如下代码:
jQuery(arg.dom).empty(); jQuery(arg.dom).xCreate([{ tagName: "A", href: "#", content: arg.data.get("shipCountry") + "1", onclick: function(){ alert(arg.data.get("shipCountry")); } },{ tagName: "A", href: "#", content: arg.data.get("shipCountry") + "2", style:"padding-left:20px", onclick: function(){ alert(arg.data.get("shipCountry")); } } ]);
数据格式化
显示效果如下的价格:
如果希望对数字或日期类型的数据做格式化的设置,可以通过DataColumn的displayFormat属性设置,如本例:
当然对于绑定DataSet的DataGrid中,我们更普遍的使用习惯还是将displayFormat配置到对应的DataType中,DataColumn中不设定displayFormat,让它自动的从DataType中获取。
自定义格式化
通过displayFormat可以做一些系统内置的格式化支持,可支持的格式化格式请参考jsdoc中的:
- Date的formatDate()
// @Bind #gridPhones.#price.onRenderCell !function(arg) { arg.dom.innerText = "平均:" + dorado.util.Common.formatFloat(arg.data.get("price"), "#,##0");//调用自定义格式化规则,并将计算结果设置到dom的innerText中。 }
表格多列合并显示
如下图中的"体积(mm)"列
它实际上是对象的三个属性拼合而成的字符串:
JS实现代码如:
//@Bind #gridPhones.#size.onRenderCell !function(arg) { var entity = arg.data; arg.dom.innerText = entity.get("size.length") + " x " + entity.get("size.width") + " x " + entity.get("size.height"); }
表格中显示按钮
效果如下图中的operation数据列:
实现办法(在Grid的onCreate中设定自定义的DataColumn的renderer对象):
var OperationCellRenderer = $extend(dorado.widget.grid.SubControlCellRenderer, { createSubControl : function(arg) { if (arg.data.rowType) return null; return new dorado.widget.Button({ toggleable : true, onClick : function(self) { var entity = arg.data, originPrice, price; if (self.get("toggled")) { originPrice = entity.get("price"); price = parseInt(originPrice * 0.8); entity.set({ discount : true, price : price, originPrice : originPrice }); } else { originPrice = entity.get("price"); price = entity.get("originPrice"); entity.set({ discount : false, price : price }); } dorado.widget.NotifyTipManager.notify(entity .get("product") + "的价格已由" + originPrice + "调整为" + price + "!"); } }); }, refreshSubControl : function(button, arg) { var storage = arg.data.get("storage"); button.set({ caption : (storage > 0) ? "折扣" : "无货", disabled : !(storage > 0), toggled : arg.data.get("discount") }); } }); // @Bind #gridPhones.onCreate !function(self) { self.set("&operation.renderer", new OperationCellRenderer()); }
表格中显示图片
效果如下图中的图片列:
可以通过实现该类的onRenderCell事件实现:
// @Bind #gridPhones.#image.onRenderCell !function(arg) { $(arg.dom).empty().xCreate( { tagName : "IMG", src : $url(">dorado/res/com/bstek/dorado/sample/data/images/" + arg.data.get("product") + "-24.png"), style : "margin: 2px" }); }
动态控制行只读或可编辑
DataGrid与DataSet绑定,当DataGrid定位行动作发生的时候会触发DataSet对应DataType的onCurrentChange事件,利用这种机制我们可以在onCurrentChange事件中动态控制Grid的可编辑特性:
// @Bind @Phone.onCurrentChange !function(self, arg, gridPhones) { if (arg.newCurrent && arg.newCurrent.get("storage")>100){ gridPhones.set("readOnly", true); }else{ gridPhones.set("readOnly", false); } }
上面的gridPhones为页面上的DataGrid。
另外由于Dorado这种数据模型编程机制,如果我们直接设置DataSet的readOnly属性,它会导致与之绑定的其他可视化控件的只读状态发生变化,如DataGrid, TextEditor, AutoForm等等,因此在更多的情况下我们会将上面的代码改写为:
// @Bind @Phone.onCurrentChange !function(self, arg, dsPhones) { if (arg.newCurrent && arg.newCurrent.get("storage")>100){ dsPhones.set("readOnly", true); }else{ dsPhones.set("readOnly", false); } }
根据行列动态决定某一个单元格只读或可编辑
与上面类似的,基于数据模型编码方式,如果想控制单个单元格的只读属性,可以通过如下方式设定:
// @Bind @Phone.onCurrentChange !function(self, arg) { if (arg.newCurrent && arg.newCurrent.get("storage")>100){ self.getPropertyDef("storage").set("readOnly", true); }else{ self.getPropertyDef("storage").set("readOnly", false); } }
如何在服务器端动态的为Grid添加DataColumn
可以利用动态视图技术实现,首先为DataGrid控件定义一个监听器,listener属性设置好。listener定义方法参考:监听器。
参考代码:
public void onGridInit(DataGrid gridProduct) { ColumnGroup columnGroup = new ColumnGroup(); columnGroup.setCaption("分组列"); DataColumn column1 = new DataColumn(); column1.setName("productId"); DataColumn column2 = new DataColumn(); column2.setName("productName"); columnGroup.addColumn(column2); gridProduct.addColumn(columnGroup); }
由于Dorado是基于数据模型管理数据的,因此你还要动态的创建DataType中对应的PropertyDef, 动态创建方法参考:动态私有DataType.
参考代码:
public void onInit(ViewConfig viewConfig) throws Exception { PropertyDef propertyDef; EntityDataType dataTypeProduct = (EntityDataType) viewConfig .getDataType("Product"); propertyDef = new BasePropertyDef("productId"); propertyDef.setDataType(viewConfig.getDataType("long")); propertyDef.setLabel("编码"); propertyDef.setReadOnly(true); dataTypeProduct.addPropertyDef(propertyDef); propertyDef = new BasePropertyDef("productName"); propertyDef.setLabel("名称"); dataTypeProduct.addPropertyDef(propertyDef); }
Attachments:











