3.5.2.1.11. 数据网格

在线示例

API 文档

DataGrid - 数据网格组件类似于表格组件, 适合用于展示、分类、排序表格类数据,由于使用了在滚动时加载数据的延迟加载方式,所以此组件具有更好的数据行、列操作性能。

gui dataGrid 1

该组件的 XML 名称为 dataGrid

以下为在 XML 文件中定义数据网格的示例:

  1. <data>
  2. <collection id="ordersDc" class="com.company.sales.entity.Order" view="order-with-customer">
  3. <loader id="ordersDl">
  4. <query>
  5. <![CDATA[select e from sales_Order e order by e.date]]>
  6. </query>
  7. </loader>
  8. </collection>
  9. </data>
  10. <layout>
  11. <dataGrid id="ordersDataGrid" dataContainer="ordersDc" height="100%" width="100%">
  12. <columns>
  13. <column id="date" property="date"/>
  14. <column id="customer" property="customer.name"/>
  15. <column id="amount" property="amount"/>
  16. </columns>
  17. </dataGrid>
  18. </layout>

其中元素里的 id 属性标识一列,property 指示数据容器实体中的属性,对应的数据库中的数据会展示在该列。

dataGrid - 数据网格中的元素:

  • columns - 必要元素,定义 DataGrid 的所有列。columns 元素有如下属性:

    • includeAll – 加载 dataContainerdatasource 中定义的 view 的所有属性。

      在下面的例子中,我们显示了 customersDc 中使用视图的所有属性。如果视图包含系统属性,也同样会显示。

      1. <dataGrid id="dataGrid"
      2. width="100%"
      3. height="100%"
      4. dataContainer="customersDc">
      5. <columns includeAll="true"/>
      6. </dataGrid>

      如果实体的视图包含引用属性,该属性会按照其实例名称进行展示。如果需要展示一个特别的属性,则需要在视图和 column 元素中定义:

      1. <columns includeAll="true">
      2. <column id="address.street"/>
      3. </columns>

      如果未指定视图,includeAll 会加载给定实体及其祖先的所有属性。

  1. - `exclude` 英文逗号分隔的属性列表,这些属性不会被加载到数据网格。
  2. 在下面的例子中,我们会显示除了 `name` `order` 之外的所有属性:
  3. ```
  4. <dataGrid id="dataGrid"
  5. width="100%"
  6. height="100%"
  7. dataContainer="customersDc">
  8. <columns includeAll="true"
  9. exclude="name, order"/>
  10. </dataGrid>
  11. ```
  12. 每一列是在嵌套的 `column` 元素中描述,该元素有如下属性:
  13. - `id` - 非必须属性,标识一列。如果没有设置,对应的 `property` 值会被用作该列的标识,所以这种时候 `property` 值是必须的。否则会抛出 `GuiDevelopmentException` 异常。如果列是在界面控制器代码中创建的,则 `id` 属性是必须的。
  14. - `property` - 指对应的实体属性。可以是数据源/数据容器实体的属性,也可以是关联实体的属性,关联实体属性前面需要加上关联类名字并通过“.”连接。例如:
  15. ```
  16. <columns>
  17. <column id="date" property="date"/>
  18. <column id="customer" property="customer"/>
  19. <column id="customerName" property="customer.name"/>
  20. <column id="customerCountry" property="customer.address.country"/>
  21. </columns>
  22. ```
  23. - `caption` - 可选属性,定义列标题。如果未设置,对应的[本地化属性名称]($af3458145e44e83a.md)会被做为列标题显示。
  24. - `expandRatio` - 设置列宽占比。默认情况下,所有列等宽(`expandRatio = 1`)。如果至少有一列设置了其它值,则忽略所有的隐式值,并且只使用设置的值。
  25. - `collapsible` - 定义用户是否可以通过 `DataGrid` 表格组件右上角的侧边栏菜单隐藏/显示该列。默认为 `true`
  26. - `collapsed` - 可选属性,设置为 `true` 时自动隐藏该列。该属性默认值为 `false`
  27. - `collapsingToggleCaption` - 设置在侧边栏菜单中该列的标题。默认为 `null`, 此时侧边栏菜单中该列的标题与数据网格中该列的标题一致。
  28. ![gui dataGrid 2](/projects/cuba-7.2-zh/331892d711a2e2c1f8672aba191fb6a8.png)
  29. - `resizable` - 定义用户是否可以调整列宽。
  30. - `sortable` - 可选属性,可以用来关闭针对该列的排序。当整个 `DataGrid` 数据网格控件的 `sortable` 属性设置为 `true`(默认值)时生效。
  31. - `width` - 可选属性,定义列宽。只支持以像素为单位的数值类型。
  32. - `minimumWidth` - 设置最小列宽,以像素为单位。
  33. - `maximumWidth` - 设置最大列宽,以像素为单位。
  34. `column` 元素可以包含一个内嵌的 [formatter]($bb388503219b31d6.md) 元素,通过它可以用不同于[数据类型]($d950809876f62062.md)的格式展示数据:
  35. ```
  36. <column id="date" property="date">
  37. <formatter class="com.haulmont.cuba.gui.components.formatters.DateFormatter"
  38. format="yyyy-MM-dd HH:mm:ss"
  39. useUserTimezone="true"/>
  40. </column>
  41. ```
  • actions - 可选元素,定义 DataGrid 数据网格的操作。除了自定义的操作,ListActionType 枚举类中定义的标准操作也支持,它们是: create(创建)、 edit(编辑)、 remove(删除)、 refresh(刷新)、 add(添加,从数据库中选择一条记录放入当前数据网格)、 exclude(移出,将所选行从当前数据网格中移出,但不会从数据库删除).
  • buttonsPanel - 按钮区 ButtonsPanel,位于 DataGrid 数据网格的上方,其中包含各操作对应的按钮。
  • rowsCount - 可选元素,会为数据网格控件创建一个行数( RowsCount )控件。行数控件会启用数据分页,在界面控制器中调用 CollectionLoader.setMaxResults() 方法可以控制数据加载器中的数据量,进而能控制每页最大行数。另外,绑定到相同数据源的通用过滤器组件也能实现此功能。

    rowsCount 控件也会显示数据结果总数,但不需要把这些数据全部加载出来。用户可以点击 “?“ 按钮, 它会调用 com.haulmont.cuba.core.global.DataManager#getCount 方法,该方法使用相同的参数请求数据库,同时使用 COUNT(*) 聚合函数代替加载数据。返回的数值会显示在 “?“ 位置。

    RowsCount 组件的 autoLoad 属性如果设置为 true,启用自动加载行数。可以在 XML 描述中设置:

    1. <rowsCount autoLoad="true"/>

    另外,在界面控制器中也可以通过 RowsCount API 启用或禁用该功能:

    1. boolean autoLoadEnabled = rowsCount.getAutoLoad();
    2. rowsCount.setAutoLoad(false);

数据网格控件属性:

  • aggregatable 属性可以启用对 DataGrid 的行进行聚合运算,支持下列运算符:

    • SUM − 和

    • AVG − 均值

    • COUNT − 计数

    • MIN − 最小值

    • MAX − 最大值

  1. 聚合 `DataGrid` 列的 `aggregation` 元素需要设置 `type` 属性,表示聚合的函数。 默认情况下,聚合列只支持数字类型,比如 `Integer``Double``Long` `BigDecimal`。聚合值会显示在 `DataGrid` 顶部的附加行内。聚合的功能与 [表格]($695f6c8ea9cf5ea3.md) 组件一致。也就是说,同样可以使用 [strategyClass]($695f6c8ea9cf5ea3.md#gui_Table_column_aggregation_strategyClass)、[valueDescription]($695f6c8ea9cf5ea3.md#gui_Table_column_aggregation_valueDescription) 和 [formatter]($695f6c8ea9cf5ea3.md#gui_Table_column_aggregation_formatter)。
  2. 带聚合列的 `DataGrid` XML 描述示例:
  3. ```
  4. <dataGrid id="ordersDataGrid"
  5. dataContainer="ordersDc"
  6. aggregationPosition="BOTTOM"
  7. aggregatable="true">
  8. <columns>
  9. <column id="customerGrade" property="customer.grade">
  10. <aggregation strategyClass="com.company.sample.CustomerGradeAggregation"
  11. valueDescription="msg://customerGradeAggregationDesc"/>
  12. </column>
  13. <column id="amount" property="amount">
  14. <aggregation type="SUM">
  15. <formatter class="com.company.sample.MyFormatter"/>
  16. </aggregation>
  17. </column>
  18. ...
  19. </columns>
  20. ...
  21. </dataGrid>
  22. ```
  • aggregationPosition 属性可以设置聚合值行的位置: TOPBOTTOM。默认为 TOP
  • columnResizeMode - 设置调整列宽时的动画效果。支持两种效果:

    • ANIMATED - 动画效果,列宽跟随鼠标拖拽(默认)。

    • SIMPLE - 简单效果,列宽会在拖拽动作结束后才发生改变。

  1. 列宽变化事件可以通过监听器 `ColumnResizeListener` 跟踪。可以使用 [isUserOriginated()]($d367e754dee84354.md#gui_api_UserOriginated) 方法跟踪列宽变化事件的来源。
  • columnsCollapsingAllowed - 允许隐藏/折叠列,定义用户是否可以在侧边栏菜单中隐藏/折叠某些列。侧边栏菜单中显示的列旁边会有复选框。当用户选择或者取消选择某列时,对应列的 collapsed 属性值会变化。当 columnsCollapsingAllowed 属性为 false 时,列对应的 collapsed 属性不能被设置为 true

    列折叠状态的变化可以通过监听器 ColumnCollapsingChangeListener 跟踪。列折叠事件的来源可以使用 isUserOriginated() 方法进行跟踪.

  • contextMenuEnabled - 开启或关闭右键菜单。默认为 true

    DataGrid 数据网格控件的右键点击事件可以通过监听器 ContextClickListener 跟踪。

  • editorBuffered - 编辑器缓冲模式开启或关闭。默认为 true
  • editorCancelCaption - 设置 DataGrid 数据网组件编辑器中取消(cancel)按钮的名称。
  • editorCrossFieldValidate - 在行内编辑器启用跨字段验证。默认为 true
  • editorSaveCaption - 设置数据网格组件编辑器中保存(save)按钮的名称。
  • frozenColumnCount - 设置固定列的个数。0 表示不需要固定任何列,除了开启多选模式时的选择列。设为 -1 的时候即使选择列也不固定。
  • headerVisible - 定义是否显示表头。默认为 true
  • reorderingAllowed - 定义用户是否可以通过鼠标拖拽重新设置列的顺序。默认值为 true

    列排序的改变事件可以通过监听器 ColumnReorderListener 跟踪。排序改变事件的来源可以通过 isUserOriginated() 方法跟踪。

  • selectionMode - 设置行选择模式,支持以下四种:

    • SINGLE - 单行选择。

    • MULTI - 多行选择。

    • MULTI_CHECK - 通过内嵌复选框列进行多选。

    • NONE - 不支持选择。

      行选中事件可以通过监听器 SelectionListener 跟踪。行选中事件的来源可以使用 isUserOriginated() 方法跟踪.

      gui dataGrid 3

  • sortable - 开启/关闭数据网格控件的排序功能。默认为 true。开启后,点击列名会在列名右边显示排序图标。使用列的 sortable 属性可以禁用该列的排序功能。

    DataGrid 的排序事件可以通过监听器 SortListener 跟踪。排序事件的来源可以通过 isUserOriginated() 方法跟踪。

  • textSelectionEnabled - 开启/关闭数据网格单元格中的文字选择功能。默认为 false

DataGrid 接口的方法:

  • getColumns() - 按当前界面的展示顺序获取列集合。

  • getSelected()getSingleSelected() - 返回所选行对应实体的实例。getSelected() 返回一个集合。如果没有选择任何行,则返回一个空的集合。如果设置的是 SelectionMode.SINGLE 单选模式,用 getSingleSelected() 会更方便,它直接返回一个被选择的实体实例,或者 null(没有选择任何行)。

  • getVisibleColumns() - 按当前界面中列的显示顺序获取用户可见的列集合。

  • scrollTo() - 将 DataGrid 滚动到指定行。需要一个实体实例做为输入参数来指定滚动到哪一行。除了实体实例参数,另有重载方法支持 ScrollDestination 参数,该参数可以为以下值:

    • ANY - 滚动尽量少的位置来展示所需要的数据。

    • START - 滚动 DataGrid ,使所需要的数据展示在可见部分的顶端。

    • MIDDLE - 滚动 DataGrid ,使所需要的数据展示在可见部分的中部。

    • END - 滚动 DataGrid ,使所需要的数据展示在可见部分的底部。

  • scrollToStart() and scrollToEnd() - 将 DataGrid 滚动到开头或结尾。
  • addCellStyleProvider() - 为 DataGrid 单元格添加 style provider。
  • addRowStyleProvider() - 为 DataGrid 行添加 style provider。
  • setEnterPressAction() - 设置按下 回车键 时需要执行的操作。如果没有定义这种操作,控件会尝试按以下顺序找一个合适的操作:

    • setItemClickAction() 方法定义的操作。

    • 通过 shortcut 快捷键属性定义给 回车键 的操作。

    • edit(编辑) 操作。

    • view(查看) 操作。

  1. 如果找到一个操作,并且其属性 `enabled` = `true`,则会执行它。
  • setItemClickAction() - 设置双击时的操作。如果没有定义,组件会按以下顺序找一个合适的操作:

    • 通过 shortcut 快捷键属性定义给 回车键 的操作。

    • edit(编辑) 操作。

    • view(查看) 操作。

  1. 如果找到一个操作并且属性 `enabled` = `true`,则会执行它。
  2. 单击事件可以通过监听器 `ItemClickListener` 跟踪。
  • sort() - 根据指定列对数据进行排序,通过枚举值 SortDirection 控制排序方式:

    • ASCENDING - 升序 (A-Z, 1..9)。

    • DESCENDING - 降序 (Z-A, 9..1)。

  • getAggregationResults() 方法返回聚合结果的映射(map),键值为 DataGrid 的列标识符,值为聚合值。

使用描述提供者:

  • setDescriptionProvider() 方法用来为每个 DataGrid 列的单元格生成可选的描述(提示)。描述支持 HTML 标记。

    1. @Inject
    2. private DataGrid<Customer> customersDataGrid;
    3. @Subscribe
    4. protected void onInit(InitEvent event) {
    5. customersDataGrid.getColumnNN("age").setDescriptionProvider(customer ->
    6. getPropertyCaption(customer, "age") +
    7. customer.getAge(),
    8. ContentMode.HTML);
    9. customersDataGrid.getColumnNN("active").setDescriptionProvider(customer ->
    10. getPropertyCaption(customer, "active") +
    11. getMessage(customer.getActive() ? "trueString" : "falseString"),
    12. ContentMode.HTML);
    13. customersDataGrid.getColumnNN("grade").setDescriptionProvider(customer ->
    14. getPropertyCaption(customer, "grade") +
    15. messages.getMessage(customer.getGrade()),
    16. ContentMode.HTML);
    17. }

    gui dataGrid 11

  • setRowDescriptionProvider() 方法用来为每个 DataGrid 行生成可选的描述(提示)。如果同时也设置了列描述提供者,只有在列描述提供者返回 null 时显示行描述提供器实例。

    1. customersDataGrid.setRowDescriptionProvider(Instance::getInstanceName);

    gui dataGrid 10

使用 DetailsGenerator:

使用 setDetailsGenerator() 方法设置 DetailsGenerator 接口,可以生成自定义控件来展示对应行的明细:

  1. @Inject
  2. private DataGrid<Order> ordersDataGrid;
  3. @Inject
  4. private UiComponents uiComponents;
  5. @Install(to = "ordersDataGrid", subject = "detailsGenerator")
  6. protected Component ordersDataGridDetailsGenerator(Order order) {
  7. VBoxLayout mainLayout = uiComponents.create(VBoxLayout.NAME);
  8. mainLayout.setWidth("100%");
  9. mainLayout.setMargin(true);
  10. HBoxLayout headerBox = uiComponents.create(HBoxLayout.NAME);
  11. headerBox.setWidth("100%");
  12. Label infoLabel = uiComponents.create(Label.NAME);
  13. infoLabel.setHtmlEnabled(true);
  14. infoLabel.setStyleName("h1");
  15. infoLabel.setValue("Order info:");
  16. Component closeButton = createCloseButton(order);
  17. headerBox.add(infoLabel);
  18. headerBox.add(closeButton);
  19. headerBox.expand(infoLabel);
  20. Component content = getContent(order);
  21. mainLayout.add(headerBox);
  22. mainLayout.add(content);
  23. mainLayout.expand(content);
  24. return mainLayout;
  25. }
  26. private Component createCloseButton(Order entity) {
  27. Button closeButton = uiComponents.create(Button.class);
  28. // ... (1)
  29. return closeButton;
  30. }
  31. private Component getContent(Order entity) {
  32. Label<String> content = uiComponents.create(Label.TYPE_STRING);
  33. content.setHtmlEnabled(true);
  34. StringBuilder sb = new StringBuilder();
  35. // ... (2)
  36. content.setValue(sb.toString());
  37. return content;
  38. }
1– 参考 DataGridDetailsGeneratorSample 类中的 createCloseButton 方法全部代码。
2– 参考 DataGridDetailsGeneratorSample 类中的 getContent 方法全部代码。

结果如图所示:

gui dataGrid 15

使用数据网格行内编辑器:

DataGrid 组件支持行内编辑器来编辑单元格数据。当用户要编辑一个数据项时,行内编辑界面会显示并自带默认的保存和取消按钮。

行内编辑器对应的方法有:

  • getEditedItem() - 返回正在被编辑的数据项。

  • isEditorActive() - 是否正在行内编辑界面编辑某个数据项。

  • editItem(Object itemId)(废弃) - 为提供了 id 的数据项打开编辑界面。如果数据项在当前界面区域不可见,数据网格会将数据项滚动到可视区域。
  • edit(Entity item) - 为指定的数据项打开编辑界面。如果数据项在当前界面区域不可见,数据网格会将数据项滚动到可视区域。

DataGrid 行内编辑器可以使用实体约束(跨字段验证)。如果有验证错误,DataGrid 会显示错误消息。开启/禁用该功能或者获取当前状态可以使用下面方法:

  • setEditorCrossFieldValidate(boolean validate) - 启用、禁用行内编辑器的跨字段验证。默认为 true

  • isEditorCrossFieldValidate() - 如果行内编辑器的跨字段验证开启,则返回 true

使用以下方法添加/删除行内编辑界面打的监听器:

  • addEditorOpenListener(), removeEditorCloseListener() - 添加/删除行内编辑界面打开监听器。

    当用户双击 DataGrid 数据网格中某个区域时,行内编辑界面打开,使用上述监听器,可以获取被编辑行的其它字段并进行需要的修改。这种方法可以使得不用关闭当前行内编辑器就能修改其它字段。

    例如:

    1. customersTable.addEditorOpenListener(editorOpenEvent -> {
    2. Map<String, Field> fieldMap = editorOpenEvent.getFields();
    3. Field active = fieldMap.get("active");
    4. Field grade = fieldMap.get("grade");
    5. ValueChangeListener listener = e ->
    6. active.setValue(true);
    7. grade.addValueChangeListener(listener);
    8. });
  • addEditorCloseListener(), removeEditorCloseListener() - 添加/删除行内编辑界面关闭监听器。
  • addEditorPreCommitListener(), removeEditorPreCommitListener() - 添加/删除行内编辑界面数据提交前监听器。
  • addEditorPostCommitListener(), removeEditorPostCommitListener() - 添加/删除行内编辑界面数据提交后监听器。

行内编辑器所做的数据修改只提交到数据源或者数据容器。需要额外的代码把他们持久化到数据库。

可以通过 EditorFieldGenerationContext 类对编辑器组件进行定制,在某一列上使用 setEditFieldGenerator() 方法设置该列数据的编辑器组件:

  1. @Inject
  2. private DataGrid<Order> ordersDataGrid;
  3. @Inject
  4. private UiComponents uiComponents;
  5. @Subscribe
  6. protected void onInit(InitEvent event) {
  7. ordersDataGrid.getColumnNN("amount").setEditFieldGenerator(orderEditorFieldGenerationContext -> {
  8. LookupField<BigDecimal> lookupField = uiComponents.create(LookupField.NAME);
  9. lookupField.setValueSource((ValueSource<BigDecimal>) orderEditorFieldGenerationContext
  10. .getValueSourceProvider().getValueSource("amount"));
  11. lookupField.setOptionsList(Arrays.asList(BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.TEN));
  12. return lookupField;
  13. });
  14. }

结果如下:

gui dataGrid 14

使用 ColumnGenerator(列生成器) 接口:

DataGrid 组件通过以下方法生成列:

  • addGeneratedColumn(String columnId, ColumnGenerator generator)

  • addGeneratedColumn(String columnId, ColumnGenerator generator, int index)

ColumnGenerator 是用来定义生成的列或者计算出的列的接口:

  • 该列每一行的数据值,

  • 该列数据类型。

下面是一个生成列的示例,这个列显示大写的用户登录名:

  1. @Subscribe
  2. protected void onInit(InitEvent event) {
  3. DataGrid.Column column = usersGrid.addGeneratedColumn("loginUpperCase", new DataGrid.ColumnGenerator<User, String>(){
  4. @Override
  5. public String getValue(DataGrid.ColumnGeneratorEvent<User> event){
  6. return event.getItem().getLogin().toUpperCase();
  7. }
  8. @Override
  9. public Class<String> getType(){
  10. return String.class;
  11. }
  12. }, 1);
  13. column.setCaption("Login Upper Case");
  14. }

结果如下:

gui dataGrid 7

ColumnGeneratorEvent 通过 getValue 方法传入, 它包含实体信息,在当前行的 ID 为 loginUpperCase 的列显示需要的数据。

默认情况下,新生成的列加在数据网格的最右边。有两种方法可以管理列的位置:代码中使用 index 或者在界面 XML 文件中提前定义好并设置 id, 然后在 addGeneratedColumn 方法中使用该 id。

使用渲染器:

数据在列中的显示方式可以通过渲染器自定义。比如想在单元格中显示图标,可以使用 ImageRenderer 类和图标路径实现:

  1. @Subscribe
  2. protected void onInit(InitEvent event) {
  3. DataGrid.Column avatar = usersGrid.addGeneratedColumn("userAvatar", new DataGrid.ColumnGenerator<User, String>() {
  4. @Override
  5. public String getValue(DataGrid.ColumnGeneratorEvent<User> event) {
  6. return "icons/user.png";
  7. }
  8. @Override
  9. public Class<String> getType() {
  10. return String.class;
  11. }
  12. }, 0);
  13. avatar.setCaption("Avatar");
  14. avatar.setRenderer(usersGrid.createRenderer(DataGrid.ImageRenderer.class));
  15. }

结果如下:

gui dataGrid 8

WebComponentRenderer 接口可以使得在数据网格单元格中显示不同的 Web 控件。以下是生成一个带查找控件的列的例子:

  1. @Inject
  2. private DataGrid<User> usersGrid;
  3. @Inject
  4. private UiComponents uiComponents;
  5. @Inject
  6. private Configuration configuration;
  7. @Inject
  8. private Messages messages;
  9. @Subscribe
  10. protected void onInit(InitEvent event) {
  11. Map<String, Locale> locales = configuration.getConfig(GlobalConfig.class).getAvailableLocales();
  12. Map<String, String> options = new TreeMap<>();
  13. for (Map.Entry<String, Locale> entry : locales.entrySet()) {
  14. options.put(entry.getKey(), messages.getTools().localeToString(entry.getValue()));
  15. }
  16. DataGrid.Column column = usersGrid.addGeneratedColumn("language",
  17. new DataGrid.ColumnGenerator<User, Component>() {
  18. @Override
  19. public Component getValue(DataGrid.ColumnGeneratorEvent<User> event) {
  20. LookupField<String> component = uiComponents.create(LookupField.NAME);
  21. component.setOptionsMap(options);
  22. component.setWidth("100%");
  23. User user = event.getItem();
  24. component.setValue(user.getLanguage());
  25. component.addValueChangeListener(e -> user.setLanguage(e.getValue()));
  26. return component;
  27. }
  28. @Override
  29. public Class<Component> getType() {
  30. return Component.class;
  31. }
  32. });
  33. column.setRenderer(new WebComponentRenderer());
  34. }

结果如下:

gui dataGrid 13

当字段类型与渲染器支持的类型不匹配时,可以创建一个 Function 来匹配模型和视图的数据类型。比如,想把布尔类型用图标展示时,可以巧妙的使用 HtmlRenderer 来做 HTML 渲染以及实现布尔类型转换为图标展示的逻辑。

  1. @Inject
  2. private DataGrid<User> usersGrid;
  3. @Subscribe
  4. protected void onInit(InitEvent event) {
  5. DataGrid.Column<User> hasEmail = usersGrid.addGeneratedColumn("hasEmail", new DataGrid.ColumnGenerator<User, Boolean>() {
  6. @Override
  7. public Boolean getValue(DataGrid.ColumnGeneratorEvent<User> event) {
  8. return StringUtils.isNotEmpty(event.getItem().getEmail());
  9. }
  10. @Override
  11. public Class<Boolean> getType() {
  12. return Boolean.class;
  13. }
  14. });
  15. hasEmail.setCaption("Has Email");
  16. hasEmail.setRenderer(
  17. usersGrid.createRenderer(DataGrid.HtmlRenderer.class),
  18. (Function<Boolean, String>) hasEmailValue -> {
  19. return BooleanUtils.isTrue(hasEmailValue)
  20. ? FontAwesome.CHECK_SQUARE_O.getHtml()
  21. : FontAwesome.SQUARE_O.getHtml();
  22. });
  23. }

结果如下:

gui dataGrid 9

渲染器可以通过两种方式创建:

  • DataGrid 接口的 set 方法中直接设置渲染器接口。

  • 为对应的模块直接创建渲染器实现:

    dataGrid.createRenderer(DataGrid.ImageRenderer.class) → new WebImageRenderer()

目前平台支持以下渲染器接口:

  • IconRenderer - 显示 CubaIcon 的渲染器。

  • TextRenderer - 显示文本。

  • HtmlRenderer - 显示 HTML 布局。

  • ProgressBarRenderer - 把 0 到 1 之间的 double 浮点值作为 ProgressBar 进度条组件显示。

  • DateRenderer - 以预定义格式显示日期。

  • NumberRenderer - 以预定义格式显示数字。

  • ButtonRenderer - 把字符串值做为按钮文字展示。

  • ImageRenderer - 将指定路径的图像显示。

  • CheckBoxRenderer - 将布尔值做为复选框显示。

表头(Header)和表尾(Footer):

HeaderRowFooterRow 接口受制于分别展示表头和表尾单元格,支持跨列合并单元格。

DataGrid 的以下方法用于创建和管理表头、表尾:

  • appendHeaderRow()appendFooterRow() - 在表头或表尾区底部添加一个新行。

  • prependHeaderRow()prependFooterRow() - 在表头或表尾区顶部添加一个新行。

  • addHeaderRowAt()addFooterRowAt() - 在表头或表尾区的指定位置添加新行。该位置及其后面的行位置顺序下移,行索引增加。

  • removeHeaderRow()removeFooterRow() - 从表头或表尾区删除指定行。

  • getHeaderRowCount()getFooterRowCount() - 获取表头或表尾区行数。

  • setDefaultHeaderRow() - 设置表头默认行。默认表头行为用户提供排序功能。

HeaderCellFooterCell 接口提供自定义静态单元格功能:

  • setStyleName() - 为单元格设置自定义样式。

  • getCellType() - 返回单元格内容类型。静态单元格枚举类型 DataGridStaticCellType 有三个值:

    • TEXT - 文本

    • HTML - HTML

    • COMPONENT - 组件

  • getComponent()getHtml()getText() - 不同类型单元格获取内容的方法。

下面这个例子中,表头包含合并的单元格,表尾显示经计算得出的值:

  1. <dataGrid id="dataGrid" datasource="countryGrowthDs" width="100%">
  2. <columns>
  3. <column property="country"/>
  4. <column property="year2017"/>
  5. <column property="year2018"/>
  6. </columns>
  7. </dataGrid>
  1. @Inject
  2. private DataGrid<CountryGrowth> dataGrid;
  3. @Inject
  4. private UserSessionSource userSessionSource;
  5. @Inject
  6. private Messages messages;
  7. @Inject
  8. private CollectionContainer<CountryGrowth> countryGrowthsDc;
  9. private DecimalFormat percentFormat;
  10. @Subscribe
  11. protected void onBeforeShow(BeforeShowEvent event) {
  12. initPercentFormat();
  13. initHeader();
  14. initFooter();
  15. initRenderers();
  16. }
  17. private DecimalFormat initPercentFormat() {
  18. percentFormat = (DecimalFormat) NumberFormat.getPercentInstance(userSessionSource.getLocale());
  19. percentFormat.setMultiplier(1);
  20. percentFormat.setMaximumFractionDigits(2);
  21. return percentFormat;
  22. }
  23. private void initRenderers() {
  24. dataGrid.getColumnNN("year2017").setRenderer(new WebNumberRenderer(percentFormat));
  25. dataGrid.getColumnNN("year2018").setRenderer(new WebNumberRenderer(percentFormat));
  26. }
  27. private void initHeader() {
  28. DataGrid.HeaderRow headerRow = dataGrid.prependHeaderRow();
  29. DataGrid.HeaderCell headerCell = headerRow.join("year2017", "year2018");
  30. headerCell.setText("GDP growth");
  31. headerCell.setStyleName("center-bold");
  32. }
  33. private void initFooter() {
  34. DataGrid.FooterRow footerRow = dataGrid.appendFooterRow();
  35. footerRow.getCell("country").setHtml("<strong>" + messages.getMainMessage("average") + "</strong>");
  36. footerRow.getCell("year2017").setText(percentFormat.format(getAverage("year2017")));
  37. footerRow.getCell("year2018").setText(percentFormat.format(getAverage("year2018")));
  38. }
  39. private double getAverage(String propertyId) {
  40. double average = 0.0;
  41. List<CountryGrowth> items = countryGrowthsDc.getItems();
  42. for (CountryGrowth countryGrowth : items) {
  43. Double value = countryGrowth.getValue(propertyId);
  44. average += value != null ? value : 0.0;
  45. }
  46. return average / items.size();
  47. }

gui dataGrid 12

数据网格样式:

可以在 XML 描述中使用 stylename 属性为 DataGrid 组件设置预定义样式。

  1. <dataGrid id="dataGrid"
  2. width="100%"
  3. height="100%"
  4. stylename="borderless"
  5. dataContainer="customersDc">
  6. </dataGrid>

或者在界面控制器使用编程的方式设置。

  1. dataGrid.setStyleName("borderless");

预定义样式:

  • borderless - DataGrid 无边线。
  • no-horizontal-lines - DataGrid 行之间无水平分割线。
  • no-vertical-lines - DataGrid 列之间无垂直分割线。
  • no-stripes - 每行背景颜色统一。

DataGrid 的展示可以使用带 $cuba-datagrid-* 前缀的 SCSS 变量进行自定义。可以在创建一个 主题扩展 或者一个 自定义主题 之后在可视化编辑器里修改这些变量的值。


DataGrid 的属性列表

aggregatable - aggregationPosition - align - caption - captionAsHtml - colspan - columnResizeMode - columnsCollapsingAllowed - contextHelpText - contextHelpTextHtmlEnabled - contextMenuEnabled - css - dataContainer - datasource - description - descriptionAsHtml - editorBuffered - editorCancelCaption - editorCrossFieldValidate - editorEnabled - editorSaveCaption - emptyStateLinkMessage - emptyStateMessage - enable - box.expandRatio - frozenColumnCount - headerVisible - height - icon - id - reorderingAllowed - responsive - rowspan - selectionMode - settingsEnabled - sortable - stylename - tabIndex - textSelectionEnabled - visible - width

DataGrid 的元素

actions - buttonsPanel - columns - rowsCount

columns 元素属性列表

includeAll - exclude

column 元素的属性列表

caption - collapsed - collapsible - collapsingToggleCaption - editable - expandRatio - id - maximumWidth - minimumWidth - property - resizable - sort - sortable - width

column 的元素

aggregation - formatter

aggregation 的属性

strategyClass - type - valueDescription

API

addGeneratedColumn - applySettings - createRenderer - edit - getAggregationResults - saveSettings - getColumns - setDescriptionProvider - addCellStyleProvider - setConverter - setDetailsGenerator - setEditorCrossFieldValidate - setEmptyStateLinkClickHandler - setEnterPressAction - setItemClickAction - setRenderer - setRowDescriptionProvider - addRowStyleProvider - sort

DataGrid 监听器

ColumnCollapsingChangeListener - ColumnReorderListener - ColumnResizeListener - ContextClickListener - EditorCloseListener - EditorOpenListener - EditorPostCommitListener - EditorPreCommitListener - ItemClickListener - SelectionListener - SortListener

预定义样式

borderless - no-horizontal-lines - no-vertical-lines - no-stripes