SMART datagrid v.1 > Concepts

[ grids ver.1.3.0]   Back  Forward

Concepts.Undoing Overview  准备中...

1. Overview

SMART datagrid格提供可以取消(Undo)或重做(Redo)用户输入或数据组修改等的选项。 数据修改可能会发生在网格数据组级别。 在网格上,将会发生在用户修改或添加行的情况,而数据组的修改,将会发生在网格上提交编辑的数据被传递至数据组或直接调用数据组API的情况。 

如果想在网格行编辑过程中实现取消或重做,就需要将GridBase.undoable指定为true。 而且,如果想在数据组实现取消或重做,就需要将DataSet.undoable指定为true。 一般来说,当为用户提供取消或重做UI时,将会把两种属性同时指定为true。 如果在运行过程中,变更undoable属性或调用DataSet.clearUndoGridBase.clearUndo,就会空出Undo栈并重新开始Undo历史记录。 

Code -1
    dataset.setUndoable(true);
    grid.setUndoable(true);

如果实现取消或重做,用户就可以在运行时间通过输入Ctrl+ZCtrl+Y等标准输入键,运行取消和重做。 在脚本中,将会通过调用GridBase.undoredo函数,运行取消和重做。 另外,可以通过调用GridBase.canUndocanRedo,确认目前是否可以分别运行取消和重做。 如果变更canUndo、canRedo状态,就会触发onUndoStateChanged事件。 

Code -2
    grid.onUndoStateChanged = function (grid, canUndo, canRedo) {
        document.getElementById("btnUndo").disabled = !canUndo;  
        document.getElementById("btnRedo").disabled = !canRedo;  
    };
    $("#btnUndo").click = function () {
        grid.undo();
    };
    $("#btnReco").click = function () {
        grid.redo();
    };

维持Undo列表和Redo列表的方式,类似于处理一般文件应用。 当各个变更调用被添加到Undo栈并且调用Undo,下个Undo位置将会移动至上个变更调用。 如果移动至Undo栈底部,canUndo将会变成false。 Redo调用移动至与Undo相反的方向,并且重新运行至最近变更调用时点。 而且,如果没有在Undo栈的中间位置进行Redo,而是添加新的变更调用,相关位置到最近保管在栈中的Redo调用将会被清除。 

2. 数据组编辑

如果数据组为undoable,将会在数据组的Undo栈, 管理可变更数据组的正式网格数据组树数据组的所有方法。 也就是说,我们可以取消和重做数据组变更。 用户可以在运行时间使用Ctrl+ZCtrl+Y键,也可以直接调用undoredo方法。 

下列表格中,已有列出被管理在两个数据组中的方法。 

Table-1  GridDataSet
MethodUIDescription
clearRows全部清除现有行。
setRows全部清除现有行,并且添加新的行。
setXmlRows全部清除现有行,并且使用XML源,添加新的行。
setRowCount变更数据行的数量。
setValue变更一个行、一个字段的值。
updateRow变更一个行的值。
updateRows同时变更多个行的值。
updateXmlRows使用XML源,同时变更多个行的值。
updateValues变更符合条件的行的值。
deleteRow删除一个行。
deleteRows删除多个行。
insertRow插入一个行。
appendRow添加一个行到最后。
insertRows插入多个行。
insertXmlRows使用XML源,插入多个行。
appendRows添加多个行到最后。
appendXmlRows使用XML源,添加多个行到最后。
moveRow移动一个行到其他位置。
moveRows同时移动多个行到其他位置。
setRowState强行变更一个行的状态。
setRowStates同时强行变更多个行的状态。
clearRowStates重置所有行的状态。
restoreUpdatedStates恢复修改行的状态。
restoreUpdatedRows恢复修改行的值。
setRowTag设置一个行的标签。
setRowTags设置多个行的标签。
unsetRowTags清除一个行以上的标签。
clearRowTags清除所有行的标签。
Table-2  TreeDataSet
MethodUIDescription
clearRows全部清除现有行。
setRows全部清除现有行,并且添加新的行。
setXmlRows全部清除现有行,并且使用XML源,添加新的行。
setJsonRows全部清除现有行,并且使用JSON数组,添加新的行。
insertDataRows使用数组,插入新的行到指定位置。
insertJsonRows使用JSON数组,插入新的行到指定位置。
insertXmlRows使用XML源,插入新的行到指定位置。
appendDataRows使用数组,添加新的行到最后。
appendJsonRows使用JSON数组,添加新的行到最后。
appendXmlRows使用XML源,添加新的行到最后。
insertRow插入一个行到指定位置。
addRow添加一个行到最后。
insertRows插入多个行到指定位置。
addRows添加多个行到最后。
deleteRow删除一个行。
deleteRows同时删除多个行。
setValue修改一个行、一个字段的值。
updateRow修改一个行。
setRowTag设置一个行的标签。
setRowTags同时设置多个行的标签。
unsetRowTags清除指定行的标签。
clearRowTags清除所有行的标签。
setRowState强行变更一个行的状态。
setRowStates强行变更多个行的状态。
clearRowStates重置所有行的状态。
3. 网格行编辑

如果将网格的undoable指定为true,当用户在运行时间修改或添加行时,将会在网格Undo栈,管理单元格单位的编辑活动。 用户可以使用Ctrl+Z键和Ctrl+Y键,分别进行Undo和Redo。 而且,也可以直接调用undoredo。 一般会按下列步骤进行。 

如同数据组的情况,如果网格Undo栈发生变化,就会触发onUndoStateChanged事件。 可以在这个事件内,确认能否运行Undo和Redo,也可以直接通过canUndocanRedo而确认。 

4. Group Action

当SMART datagrid格体现除基本提供的用户界面以外的、应用所需的特殊UI时,有必要通过同时调用两个以上的数据组方法,而使用户看作是一个调用。 也就是说,如果是需要只使用Ctrl+ZCtrl+Y键而运行Undo、Redo的情况,就可以使用GroupAction。 

如下列代码,我们可以通过两种方法而创建和运行GroupAction。 首先,向数据组请求GroupAction,并且在返回的GroupAction,添加将要运行的方法。 此后,再向数据组请求运行GroupAciton即可。 

Code -3
    // 请求新的group action
    var ga = ds.createActionGroup();
    // 添加变更操作
    ga.updateRow(0, values);
    ga.deleteRows([1, 2]);
    ga.insertRow(1, newValues[0]);
    ga.insertRow(2, newValues[1]);
    // 请求运行。
    ds.execute(ga);

类似于上述方式,可以通过使用数据组的beginActionsendActions而体现。 与createActionGroup不同的是, 如果不通过在beginActionsendActions之间隐式返回的GroupAction,就无法调用相关数据组的其他变更方法。 

Code -4
    // 请求新的group action
    ds.beginActions();
    // 添加变更操作
    ds.updateRow(0, values);
    ds.deleteRows([1, 2]);
    ds.insertRow(1, newValues[0]);
    ds.insertRow(2, newValues[1]);
    // 请求运行。
    ds.endActions();

需要注意的是,GroupAction不是与数据库事务一同处理的。 也就是说,并不是包含在组中的所有变更请求都会被运行或失败。 发生失败之前的变更将会反映到数据组,并且到该时点为止的记录将会被保管在数据组栈。 

5. Edit Actions

除用户编辑的数据单元格以外,还可以返回删除所选行以及清除选中区域的值。 而且,还可以返回使用AutoFill柄的数据编辑。 

这些都会在内部通过单位编辑行为而定义,并且通过Undo/Redo栈而管理单位行为。 数据组的数据修改API函数,也是通过行为而管理的。 

6. Bookmark
7. 例外处理

通常情况下,根据用户变更而被调用的方法,将会在运行变更之前,触发确认事件,并且在变更后,触发提交事件。 例如,GridDataSet.deleteRow将会在删除行之前,触发onRowDeleting事件, 而如果在事件处理器中明确返回Boolean false或抛出例外,就会中断删除操作。 而且,提交删除后,将会触发onRowDeleted事件。 

如果DataSet为undoable,就需要考虑在连续运行和取消或重做等变更方法流程中,防止数据组发生歪曲的现象。 而且,需要尽量保存运行记录。 为此,SMART datagrid格体现相关例外的简明的政策。 

运行中的例外
Undo/Redo中的例外
8. Group Action中的例外处理

如上述说明,对于最终用户,GroupAction只是一种单位行为,但数据组变更将会以包含在组中的请求单位而运行。 

运行中的例外
Undo/Redo中的例外
9. UI问题

因为"打开文件后开始编辑。"是一般的用户体验,所以DataSet的Undoable状态需要在尽量加载最初数据组后开始。 另外,根据情况,在上传已变更的数据组到服务器等之后, 通过调用DataSet.clearUndoGridBase.clearUndo,空出Undo栈并重新开始,将会是比较适当的UI。 

10. 性能问题

如果DataSet变成undoable状态,变更数据组的值的所有单位调用记录,基本上将会与复原所需信息一同储存到Undo栈。 其中,将会包含用于调用函数的参数和需要保管的值。 因此,需要注意的是,不去保管用户界面上的不必要的数据。 特别是,需要在加载初期数据组后允许undoable,并且在传送编辑数据组到服务器后,通过clearUndo而重置栈。 

See Also
DataSet.undoable
DataSet.clearUndo
GridBase.undoable
GridBase.clearUndo
GridBase.undo
GridBase.redo
GridBase.canUndo
GridBase.canRedo
GridBase.onUndoStateChanged
EditOptions.undoable
EditOptions.deletable
EditOptions.erasable
EditOptions.cancelWhenUndo
GridBase.deleteSelection
GridBase.eraseSelection
AutoFill
Examples
取消和重做