Wijmo 5

MultiRow 101

此页面展示了如何入门Wijmo的 MultiRow控件。

入门

MultiRow 控件扩展了常规的表单布局,使用多行来表示每个数据项。(它应该有一个更加准确的名字‘MultiRowPerRecordGrid’,但是实在太长了)。

MultiRow 控件允许用户以表格形式查看和编辑数据,就像普通的表单一样。不同的是。MultiRow 允许您绑定一个数据项到多行上,以创建类似表单的界面,使用最小的水平滚动条展示很大量的列。

MultiRow 控件继承自FlexGrid控件,如果会使用FlexGrid,那么您一定可以使用MultiRow 。 主要新增的属性为layoutDefinition,它接受一个描述表单行和单元格布局的对象。

MultiRow 控件不只是常规表单的简单替代,在一些场景中,它非常适用。

为了在您的应用程序中使用MultiRow控件,需要添加对wijmo, wijmo.grid,和wijmo.grid.multirow模块的引用。然后通过在页面中添加宿主元素或者AngularJs的wj-multi-row指令来实例化MultiRow

<!DOCTYPE html> <html> <head> <link href="styles/vendor/wijmo.css" rel="stylesheet" /> <script src="scripts/vendor/wijmo.min.js"></script> <script src="scripts/vendor/wijmo.grid.min.js"></script> <script src="scripts/vendor/wijmo.grid.multirow.min.js"></script> <head> <body> <!-- using AngularJS --> <wj-multi-row items-source="data" layout-definition="layoutDef"> </wj-multi-row> <!-- using pure JS --> <div id="multirow"></div> </body> </html>
onload = function() { // create and initialize the MultiRow using pure JavaScript var theMultiRow = new wijmo.grid.multirow.MultiRow('#multirow', { itemsSource: getData(), columnLayout: getColumnLayout() }); }

多行布局定义

MultiRow 控件使用多行来展示每一条记录。记录布局通过layoutDefinition 属性定义。

layoutDefinition 包含了cell group对象数组。cell group对象拥有以下属性:

下面的例子说明了layoutDefiniton 属性的用法:

现在,让我们来使用MultiRow不同的布局来展示相同的数据。使用combo box 去选择一种布局和表单的数据分组方式。 注意,MultiRow 控件提供所有的通用表单特点,包含编辑,排序,过滤和列宽:

<wj-multi-row items-source="orders" layout-definition="layoutDefs.currentItem.def"> </wj-multi-row> <wj-combo-box items-source="layoutDefs" display-member-path="name" selected-index-changed="layoutDefChanged(s,e)"> </wj-combo-box> <p> {​{layoutDefs.currentItem.description}}</p>
// 例子的布局定义 $scope.layoutDefs = new wijmo.collections.CollectionView([ { name: 'Traditional', description: 'Traditional grid view, with one row per record. The user must scroll horizontally to see the whole record.', def: [ { cells: [{ binding: 'id', header:'ID' }]}, { cells: [{ binding: 'date', header:'Ordered' }]}, { cells: [{ binding: 'shippedDate', header:'Shipped' }]}, // ... 每列一组 ... ] }, { name: 'Compact', description: 'This view uses two rows per record. The layout is divided into three column groups: order, customer, and shipper', def: [ { header: 'Order', colspan: 2, cells: [ { binding: 'id', header: 'ID' }, { binding: 'date', header: 'Ordered' }, { binding: 'amount', header: 'Amount' }, { binding: 'shippedDate', header: 'Shipped' } ] }, // ... 两个小组,为客户和托运人 ... ] }, { name: 'Detailed', description: 'This view uses three rows per record. The layout is divided into three column groups: order, customer, and shipper', def: [ { header: 'Order', colspan: 2, cells: [ { binding: 'id', header: 'ID', colspan: 2 }, { binding: 'amount', header: 'Amount', colspan: 2 }, { binding: 'date', header: 'Ordered' }, { binding: 'shippedDate', header: 'Shipped' } ] }, // ... 两个小组,为客户和托运人 ... ] } ]);

Result (live):

{{layoutDefs.currentItem.description}}

layoutDefinition 属性定义了单元格的布局方式。它包含由单元格组对象组成的数组。每个单元格组定义组的跨列数和组成每一个组的单元格。

下面的图说明了一个单元格组的解释方式和怎样转化为网格布局。

cell group

上面组包含三个列,共包含6个具有不同跨度的单元格。当生成网格布局时,表单在一行尽可能适应多的单元格。当跨列数满时,折叠到下一行。每一行的最后一个单元格将会自动伸展用来适应组的 colspan。 这个过程与折行创建新的段落很相似。

layoutDefinition对象中的多个组的也会应用相同的处理过程。

可折叠的列标题

默认情况下, MultiRow 控件会创建跨行的列标题并且为每一个 layoutDefinition定义的单元格展示列标题。

那些特定单元格的列标题将会用来排序或者过滤数据,就像常规表单一样。

在某些情况下,你可能想将列标题折叠为一行,只展示组名而不是每一个列标题。这将会节省单元格列标题占用的空间。为了折叠列标题,设置collapsedHeaders属性为真。 在那些场景下,记住在组上设置header 属性,因此列标题将不为空。

<wj-multi-row items-source="orders" layout-definition="ldThreeLines" collapsed-headers="true" collapsible-headers="true" control="hdrGrid"> </wj-multi-row> <label> <input type="checkbox" ng-model="hdrGrid.collapsedHeaders"> CollapsedHeaders </label> <label> <input type="checkbox" ng-model="hdrGrid.showHeaderCollapseButton"> Show Header Collapse Button </label>
// no code required

Result (live):


记录,组和单元格样式

在大多数的应用中,你可能想展示每一个条记录和每一个分组的起始位置与结束位置。MultiRow 控件通过向每组第一和最后的行列的单元格元素添加类样式来实现。这些类名分别是 wj-record-start, wj-record-end, wj-group-start, 和 wj-group-end.

下面的列子展示了如何使用那些CSS类样式来定制记录和分组分隔符的外观,它展示了如何使用标准的cssClass 属性 来定制组中指定单元格的外观。

<wj-multi-row class="multirow-css" items-source="orders" layout-definition="ldThreeLines"> </wj-multi-row>
/* custom styling for a MultiRow */ .multirow-css .wj-cell.wj-record-end:not(.wj-header) { border-bottom-color: #8fabff; /* blue lines between records */ } .multirow-css .wj-cell.wj-group-end { border-right-color: #bc5505; /* brown lines between groups */ } .multirow-css .wj-cell.id { color: #c0c0c0; } .multirow-css .wj-cell.amount { color: #014701; font-weight: bold; } .multirow-css .wj-cell.email { color: #0010c0; text-decoration: underline; }

Result (live):

分组

MultiRow 控件支持CollectionView-based 分组,就像标准的FlexGrid。为了使用分组,需要根据原始数据来创建一个CollectionView ,并且添加一个或多个 GroupDescription 对象到集合的 GroupDescriptions数组。

<wj-multi-row items-source="groupedOrders" layout-definition="ldThreeLines" group-header-format="City: <b>{value} </b>({count:n0} items)" control="groupingGrid"> </wj-multi-row> <label> <input type="checkbox" ng-model="groupingGrid.showGroups"> Show Groups </label> <br /> <button class="btn" ng-click="groupingGrid.collapseGroupsToLevel(0)"> Collapse All </button> <button class="btn" ng-click="groupingGrid.collapseGroupsToLevel(10)"> Expand All </button>
// expose grouped orders to the controller $scope.groupedOrders = new wijmo.collections.CollectionView(orders, { groupDescriptions: [ 'customer.city', ], newItemCreator: function () { return { // add empty customer and shipper objects to new orders customer: {}, shipper: {} } }, });

Result (live):


过滤

The MultiRow 控件支持过滤,就像标准的FlexGrid控件。

过滤功能是 wijmo.grid.filter.FlexGridFilter 类来提供。为了向MultiRow控件添加一个过滤界面,需要创建一个 FlexGridFilter控件,并且将 MultiRow 作为一个参数传递到构造函数中。

如果你想使用AngularJs,你也需要通过指令wj-flex-grid-filter 添加一个过滤器到表单中,它作为表单指令的子指令。

<wj-multi-row items-source="orders" layout-definition="ldThreeLines" initialized="initFlexFilter(s, e)"> </wj-multi-row>
// add a filter to the MultiRow $scope.initFlexFilter = function (s, e) { var filter = new wijmo.grid.filter.FlexGridFilter(s); }

Result (live):

冻结行和列

MultiRow 允许您冻结行和列,它们将在用户滚动表单的过程中保持位置不变。被冻结的单元格可以被编辑和选择,与Excel和FlexGrid控件中的表现完全一样。

下面的例子允许你切换是否行和列的第一组被冻结。

<wj-multi-row items-source="orders" layout-definition="ldTwoLines" control="frozenGrid"> </wj-multi-row> <button class="btn btn-default" ng-click="toggleFreeze(2, 2)"> {​{ frozenGrid.frozenRows == 0 ? 'Freeze' : 'Unfreeze' }} </button>
// toggle frozen rows/columns $scope.toggleFreeze = function (rows, cols) { var flex = $scope.frozenGrid; if (flex) { flex.frozenColumns = flex.frozenColumns ? 0 : cols; flex.frozenRows = flex.frozenRows ? 0 : rows; } }
/* custom styling for frozen cells */ .wj-cell.wj-frozen:not(.wj-header):not(.wj-group):not(.wj-state-selected):not(.wj-state-multi-selected) { background-color: #f3fbcc; }

Result (live):

分页

MultiRow 支持通过 IPagedCollectionView接口进行分页,该接口与.NET 中一个接口非常相似。 为了进行分页,需要设置 IPagedCollectionView.pageSize 属性为一页中项的数量,并提供一个导航栏UI。

在下面的例子中,我们使用JavaScript在一页中展示4项。 我们添加导航按钮并且在按钮点击指令中调用IPagedCollectionView 方法。 我们使用pageIndexpageCount属性去展示当前的页面和总页数。

<wj-multi-row items-source="pagedOrders" layout-definition="ldThreeLines"> </wj-multi-row> <div class="btn-group"> <button type="button" class="btn" ng-click="pagedOrders.moveToFirstPage()"> <span class="glyphicon glyphicon-fast-backward"></span> </button> <button type="button" class="btn" ng-click="pagedOrders.moveToPreviousPage()"> <span class="glyphicon glyphicon-step-backward"></span> </button> <button type="button" class="btn" disabled style="width:100px"> {{pagedOrders.pageIndex + 1 | number}} / {{pagedOrders.pageCount | number}} </button> <button type="button" class="btn" ng-click="pagedOrders.moveToNextPage()"> <span class="glyphicon glyphicon-step-forward"></span> </button> <button type="button" class="btn" ng-click="pagedOrders.moveToLastPage()"> <span class="glyphicon glyphicon-fast-forward"></span> </button> </div>
// expose paged orders to the controller $scope.pagedOrders = new wijmo.collections.CollectionView(orders, { pageSize: 4 });

Result (live):

添加和移除记录

MultiRow 控件支持 FlexGrid 控件提供的 allowAddNewallowDelete 属性。

设置 allowAddNew属性为真将会导致在表单底部展示 '新行模板' 行的集合。当用户在一个新的行模板中开始编辑一个单元格,一个新项将会添加到数据源集合。 当用户结束编辑新项(通过移除选中或者焦点),这个新项就会被提交。

设置allowDelete 属性为真将会导致表单监控键盘事件,当一整行被选中并且用户点击了‘Delete’键时,那么这行就会被删除。

<wj-multi-row items-source="addNewOrders" layout-definition="ldThreeLines" show-groups="false" allow-add-new="true" allow-delete="true" control="addNewGrid"> </wj-multi-row> <label> <input type="checkbox" ng-model="addNewGrid.allowAddNew"> Allow Add New </label> <br/> <label> <input type="checkbox" ng-model="addNewGrid.allowDelete"> Allow Delete </label>
// create 'addNewOrders' collection, start with last item selected $scope.addNewOrders = new wijmo.collections.CollectionView(orders); $scope.addNewOrders.moveCurrentToLast();
/* custom styling for new row templates */ .wj-cell.wj-new:not(.wj-header):not(.wj-group):not(.wj-state-selected):not(.wj-state-multi-selected) { background-color: #f3fbcc; }

Result (live):