找回密码
 立即注册

QQ登录

只需一步,快速开始

l2000

注册会员

1

主题

4

帖子

83

积分

注册会员

积分
83
最新发帖
l2000
注册会员   /  发表于:2020-11-19 00:07  /   查看:3856  /  回复:6
MultiRow控件,想实现每行下拉框里的可选项数目不一样,尝试利用DataMap,但是效果是同一列的下拉框内的可选项一致。如何实现第一行下拉框里的可选项是A,B,C,第二行下拉框里可选项是B,C。

6 个回复

倒序浏览
KevinChen讲师达人认证 悬赏达人认证 SpreadJS 开发认证
论坛元老   /  发表于:2020-11-19 09:54:43
沙发
你好,可以采用自定义编辑框的方法实现:
https://demo.grapecity.com.cn/wi ... ustomEditors/purejs
回复 使用道具 举报
l2000
注册会员   /  发表于:2020-11-19 10:57:51
板凳
你好,我看了下这个自定义编辑器。实现的是下拉框的样式自定义,但是同一列的下拉框里的内容是一样的,例如Product这一列,都是3个选项
        { id: 0, name: 'Widget', unitPrice: 23.43 },
        { id: 1, name: 'Gadget', unitPrice: 12.33 },
        { id: 2, name: 'Doohickey', unitPrice: 53.07 }
------------------------------------------------------------
有没有第一行内只显示2个选项,
{ id: 0, name: 'Widget', unitPrice: 23.43 },
{ id: 1, name: 'Gadget', unitPrice: 12.33 },
第二行内显示3个选项,
{ id: 0, name: 'Widget', unitPrice: 23.43 },
{ id: 1, name: 'Gadget', unitPrice: 12.33 },
{ id: 2, name: 'Doohickey', unitPrice: 53.07 }
这样的示例,谢谢
回复 使用道具 举报
l2000
注册会员   /  发表于:2020-11-19 12:03:52
地板
你好,已经实现了,需要重写DataMap的getDisplayValues()这个方法
回复 使用道具 举报
KevinChen讲师达人认证 悬赏达人认证 SpreadJS 开发认证
论坛元老   /  发表于:2020-11-19 13:01:55
5#
由于是完全自定义的编辑器,所以可以自由配置,根据条件动态修改。我改了个示例,你参考一下:

关键代码如图:


完整代码如下:
  1. import 'bootstrap.css';
  2. import '@grapecity/wijmo.styles/wijmo.css';
  3. import './styles.css';
  4. import * as wjGrid from '@grapecity/wijmo.grid';
  5. import * as wjInput from '@grapecity/wijmo.input';
  6. import * as wjCore from '@grapecity/wijmo';
  7. //
  8. // *** CustomGridEditor class (transpiled from TypeScript) ***
  9. //
  10. export class CustomGridEditor {
  11.     /**
  12.      * Initializes a new instance of a CustomGridEditor.
  13.      */
  14.     constructor(flex, binding, edtClass, options) {
  15.         // save references
  16.         this._grid = flex;
  17.         this._col = flex.columns.getColumn(binding);
  18.         // create editor
  19.         this._ctl = new edtClass(document.createElement('div'), options);
  20.         // connect grid events
  21.         flex.beginningEdit.addHandler(this._beginningEdit, this);
  22.         flex.sortingColumn.addHandler(() => {
  23.             this._commitRowEdits();
  24.         });
  25.         flex.scrollPositionChanged.addHandler(() => {
  26.             if (this._ctl.containsFocus()) {
  27.                 flex.focus();
  28.             }
  29.         });
  30.         flex.selectionChanging.addHandler((s, e) => {
  31.             if (e.row != s.selection.row) {
  32.                 this._commitRowEdits();
  33.             }
  34.         });
  35.         // connect editor events
  36.         this._ctl.addEventListener(this._ctl.hostElement, 'keydown', (e) => {
  37.             switch (e.keyCode) {
  38.                 case wjCore.Key.Tab:
  39.                 case wjCore.Key.Enter:
  40.                     e.preventDefault(); // TFS 255685
  41.                     this._closeEditor(true);
  42.                     this._grid.focus();
  43.                     // forward event to the grid so it will move the selection
  44.                     var evt = document.createEvent('HTMLEvents');
  45.                     evt.initEvent('keydown', true, true);
  46.                     'altKey,metaKey,ctrlKey,shiftKey,keyCode'.split(',').forEach((prop) => {
  47.                         evt[prop] = e[prop];
  48.                     });
  49.                     this._grid.hostElement.dispatchEvent(evt);
  50.                     break;
  51.                 case wjCore.Key.Escape:
  52.                     this._closeEditor(false);
  53.                     this._grid.focus();
  54.                     break;
  55.             }
  56.         });
  57.         // close the editor when it loses focus
  58.         this._ctl.lostFocus.addHandler(() => {
  59.             setTimeout(() => {
  60.                 if (!this._ctl.containsFocus()) {
  61.                     this._closeEditor(true); // apply edits and close editor
  62.                     this._grid.onLostFocus(); // commit item edits if the grid lost focus
  63.                 }
  64.             });
  65.         });
  66.         // commit edits when grid loses focus
  67.         this._grid.lostFocus.addHandler(() => {
  68.             setTimeout(() => {
  69.                 if (!this._grid.containsFocus() && !CustomGridEditor._isEditing) {
  70.                     this._commitRowEdits();
  71.                 }
  72.             });
  73.         });
  74.         // open drop-down on f4/alt-down
  75.         this._grid.addEventListener(this._grid.hostElement, 'keydown', (e) => {
  76.             // open drop-down on f4/alt-down
  77.             this._openDropDown = false;
  78.             if (e.keyCode == wjCore.Key.F4 ||
  79.                 (e.altKey && (e.keyCode == wjCore.Key.Down || e.keyCode == wjCore.Key.Up))) {
  80.                 var colIndex = this._grid.selection.col;
  81.                 if (colIndex > -1 && this._grid.columns[colIndex] == this._col) {
  82.                     this._openDropDown = true;
  83.                     this._grid.startEditing(true);
  84.                     e.preventDefault();
  85.                 }
  86.             }
  87.             // commit edits on Enter (in case we're at the last row, TFS 268944)
  88.             if (e.keyCode == wjCore.Key.Enter) {
  89.                 this._commitRowEdits();
  90.             }
  91.         }, true);
  92.         // close editor when user resizes the window
  93.         // REVIEW: hides editor when soft keyboard pops up (TFS 326875)
  94.         window.addEventListener('resize', () => {
  95.             if (this._ctl.containsFocus()) {
  96.                 this._closeEditor(true);
  97.                 this._grid.focus();
  98.             }
  99.         });
  100.     }
  101.     // gets an instance of the control being hosted by this grid editor
  102.     get control() {
  103.         return this._ctl;
  104.     }
  105.     // handle the grid's beginningEdit event by canceling the built-in editor,
  106.     // initializing the custom editor and giving it the focus.
  107.     _beginningEdit(grid, args) {
  108.         // check that this is our column
  109.         if (grid.columns[args.col] != this._col) {
  110.             return;
  111.         }
  112.         // check that this is not the Delete key
  113.         // (which is used to clear cells and should not be messed with)
  114.         var evt = args.data;
  115.         if (evt && evt.keyCode == wjCore.Key.Delete) {
  116.             return;
  117.         }
  118.         // cancel built-in editor
  119.         args.cancel = true;
  120.         // save cell being edited
  121.         this._rng = args.range;
  122.         CustomGridEditor._isEditing = true;
  123.         // initialize editor host
  124.         var rcCell = grid.getCellBoundingRect(args.row, args.col), rcBody = document.body.getBoundingClientRect(), ptOffset = new wjCore.Point(-rcBody.left, -rcBody.top), zIndex = (args.row < grid.frozenRows || args.col < grid.frozenColumns) ? '3' : '';
  125.         wjCore.setCss(this._ctl.hostElement, {
  126.             position: 'absolute',
  127.             left: rcCell.left - 1 + ptOffset.x,
  128.             top: rcCell.top - 1 + ptOffset.y,
  129.             width: rcCell.width + 1,
  130.             height: grid.rows[args.row].renderHeight + 1,
  131.             borderRadius: '0px',
  132.             zIndex: zIndex,
  133.         });
  134.         // initialize editor content
  135.         debugger;
  136.         // 在这里动态修改下拉项(偶数行):
  137.         if(this._col.binding == "country" && args.row % 2 == 0){
  138.             // 保存数据源
  139.             if(!this._ctlSourceCollection){
  140.                 this._ctlSourceCollection = this._ctl.collectionView.sourceCollection;
  141.             }
  142.             this._ctl.collectionView.sourceCollection = ["China"];
  143.         }else{
  144.             this._ctl.collectionView.sourceCollection = this._ctlSourceCollection;
  145.         }

  146.         if (!wjCore.isUndefined(this._ctl['text'])) {
  147.             this._ctl['text'] = grid.getCellData(this._rng.row, this._rng.col, true);
  148.         }
  149.         else {
  150.             throw 'Can\'t set editor value/text...';
  151.         }
  152.         // start editing item
  153.         var ecv = grid.editableCollectionView, item = grid.rows[args.row].dataItem;
  154.         if (ecv && item && item != ecv.currentEditItem) {
  155.             setTimeout(function () {
  156.                 grid.onRowEditStarting(args);
  157.                 ecv.editItem(item);
  158.                 grid.onRowEditStarted(args);
  159.             }, 50); // wait for the grid to commit edits after losing focus
  160.         }
  161.         // activate editor
  162.         document.body.appendChild(this._ctl.hostElement);
  163.         this._ctl.focus();
  164.         setTimeout(() => {
  165.             // get the key that triggered the editor
  166.             var key = (evt && evt.charCode > 32)
  167.                 ? String.fromCharCode(evt.charCode)
  168.                 : null;
  169.             // get input element in the control
  170.             var input = this._ctl.hostElement.querySelector('input');
  171.             // send key to editor
  172.             if (input) {
  173.                 if (key) {
  174.                     input.value = key;
  175.                     wjCore.setSelectionRange(input, key.length, key.length);
  176.                     var evtInput = document.createEvent('HTMLEvents');
  177.                     evtInput.initEvent('input', true, false);
  178.                     input.dispatchEvent(evtInput);
  179.                 }
  180.                 else {
  181.                     input.select();
  182.                 }
  183.             }
  184.             // give the control focus
  185.             if (!input && !this._openDropDown) {
  186.                 this._ctl.focus();
  187.             }
  188.             // open drop-down on F4/alt-down
  189.             if (this._openDropDown && this._ctl instanceof wjInput.DropDown) {
  190.                 this._ctl.isDroppedDown = true;
  191.                 this._ctl.dropDown.focus();
  192.             }
  193.         }, 50);
  194.     }
  195.     // close the custom editor, optionally saving the edits back to the grid
  196.     _closeEditor(saveEdits) {
  197.         if (this._rng) {
  198.             var flexGrid = this._grid, ctl = this._ctl, host = ctl.hostElement;
  199.             // raise grid's cellEditEnding event
  200.             var e = new wjGrid.CellEditEndingEventArgs(flexGrid.cells, this._rng);
  201.             flexGrid.onCellEditEnding(e);
  202.             // save editor value into grid
  203.             if (saveEdits) {
  204.                 if (!wjCore.isUndefined(ctl['value'])) {
  205.                     this._grid.setCellData(this._rng.row, this._rng.col, ctl['value']);
  206.                 }
  207.                 else if (!wjCore.isUndefined(ctl['text'])) {
  208.                     this._grid.setCellData(this._rng.row, this._rng.col, ctl['text']);
  209.                 }
  210.                 else {
  211.                     throw 'Can\'t get editor value/text...';
  212.                 }
  213.                 this._grid.invalidate();
  214.             }
  215.             // close editor and remove it from the DOM
  216.             if (ctl instanceof wjInput.DropDown) {
  217.                 ctl.isDroppedDown = false;
  218.             }
  219.             host.parentElement.removeChild(host);
  220.             this._rng = null;
  221.             CustomGridEditor._isEditing = false;
  222.             // raise grid's cellEditEnded event
  223.             flexGrid.onCellEditEnded(e);
  224.         }
  225.     }
  226.     // commit row edits, fire row edit end events (TFS 339615)
  227.     _commitRowEdits() {
  228.         var flexGrid = this._grid, ecv = flexGrid.editableCollectionView;
  229.         this._closeEditor(true);
  230.         if (ecv && ecv.currentEditItem) {
  231.             var e = new wjGrid.CellEditEndingEventArgs(flexGrid.cells, flexGrid.selection);
  232.             ecv.commitEdit();
  233.             setTimeout(() => {
  234.                 flexGrid.onRowEditEnding(e);
  235.                 flexGrid.onRowEditEnded(e);
  236.                 flexGrid.invalidate();
  237.             });
  238.         }
  239.     }
  240. }
  241. //
  242. document.readyState === 'complete' ? init() : window.onload = init;
  243. //
  244. function init() {
  245.     //
  246.     // create some random data
  247.     var countries = 'US,Germany,UK,Japan,Italy,Greece'.split(',');
  248.     var products = [
  249.         { id: 0, name: 'Widget', unitPrice: 23.43 },
  250.         { id: 1, name: 'Gadget', unitPrice: 12.33 },
  251.         { id: 2, name: 'Doohickey', unitPrice: 53.07 }
  252.     ];
  253.     var data = [];
  254.     var dt = new Date();
  255.     for (var i = 0; i < 100; i++) {
  256.         data.push({
  257.             id: i,
  258.             date: new Date(dt.getFullYear(), i % 12, 25, i % 24, i % 60, i % 60),
  259.             time: new Date(dt.getFullYear(), i % 12, 25, i % 24, i % 60, i % 60),
  260.             country: countries[Math.floor(Math.random() * countries.length)],
  261.             product: products[Math.floor(Math.random() * products.length)].name,
  262.             amount: Math.random() * 10000 - 5000,
  263.             discount: Math.random() / 4
  264.         });
  265.     }
  266.     //
  267.     // grid with custom editors
  268.     var theGrid = new wjGrid.FlexGrid('#theGrid', {
  269.         keyActionTab: 'CycleOut',
  270.         autoGenerateColumns: false,
  271.         itemsSource: data,
  272.         columns: [
  273.             { header: 'ID', binding: 'id', width: 40, isReadOnly: true },
  274.             { header: 'Date', binding: 'date', format: 'd' },
  275.             { header: 'Time', binding: 'time', format: 't' },
  276.             { header: 'Country', binding: 'country' },
  277.             { header: 'Product', binding: 'product' },
  278.             { header: 'Amount', binding: 'amount', format: 'n2' }
  279.         ],
  280.     });
  281.     //
  282.     // add custom editors to the grid
  283.     new CustomGridEditor(theGrid, 'date', wjInput.InputDate, {
  284.         format: 'd'
  285.     });
  286.     new CustomGridEditor(theGrid, 'time', wjInput.InputTime, {
  287.         format: 't',
  288.         min: new Date(2000, 1, 1, 7, 0),
  289.         max: new Date(2000, 1, 1, 22, 0),
  290.         step: 30
  291.     });
  292.     new CustomGridEditor(theGrid, 'country', wjInput.ComboBox, {
  293.         itemsSource: countries
  294.     });
  295.     new CustomGridEditor(theGrid, 'amount', wjInput.InputNumber, {
  296.         format: 'n2',
  297.         step: 10
  298.     });
  299.     //
  300.     // create an editor based on a ComboBox
  301.     var multiColumnEditor = new CustomGridEditor(theGrid, 'product', wjInput.ComboBox, {
  302.         headerPath: 'name',
  303.         displayMemberPath: 'name',
  304.         itemsSource: products
  305.     });
  306.     //
  307.     // customize the ComboBox to show multiple columns
  308.     var combo = multiColumnEditor.control;
  309.     combo.listBox.formatItem.addHandler(function (s, e) {
  310.         e.item.innerHTML = '<table><tr>' +
  311.             '<td style="width:30px;text-align:right;padding-right:6px">' + e.data.id + '</td>' +
  312.             '<td style="width:100px;padding-right:6px"><b>' + e.data.name + '</b></td>' +
  313.             '<td style="width:80px;text-align:right;padding-right:6px">' +
  314.             wjCore.Globalize.format(e.data.unitPrice, 'c') +
  315.             '</td>' +
  316.             '</tr></table>';
  317.     });
  318. }
  319. //# sourceMappingURL=CustomGridEditor.js.map
复制代码


以上代码替换学习指南demo中的app.js,点击运行。
双击国家列可以看到效果。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复 使用道具 举报
l2000
注册会员   /  发表于:2020-11-19 14:13:46
6#
好的,谢谢
回复 使用道具 举报
KevinChen讲师达人认证 悬赏达人认证 SpreadJS 开发认证
论坛元老   /  发表于:2020-11-19 20:29:27
7#
不客气,有问题欢迎继续交流
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 立即注册
返回顶部