Mvvm 绑定到KendoUI树视图中的嵌套数组值

Mvvm 绑定到KendoUI树视图中的嵌套数组值,mvvm,kendo-ui,treeview,kendo-treeview,Mvvm,Kendo Ui,Treeview,Kendo Treeview,我们正在评估KendouiWeb在我们所有项目中的使用情况,我在TreeView小部件方面遇到了一个问题(或缺乏理解) 我试图使用MVVM树视图,但在从模板绑定到嵌套数组值时遇到问题。我通过单击按钮添加一个节点及其子节点来动态构建树视图。我想将每个叶(子)节点绑定到MVVM中该节点上的文本值。这在树的初始加载上似乎非常有效,但在向viewModel添加更多节点后,绑定似乎停止工作 这似乎比我感觉的要困难得多,这让我觉得我错过了什么 有人能帮忙解释一下吗 谢谢 杰森 JSFIDLE 我创建了一个J

我们正在评估KendouiWeb在我们所有项目中的使用情况,我在TreeView小部件方面遇到了一个问题(或缺乏理解)

我试图使用MVVM树视图,但在从模板绑定到嵌套数组值时遇到问题。我通过单击按钮添加一个节点及其子节点来动态构建树视图。我想将每个叶(子)节点绑定到MVVM中该节点上的文本值。这在树的初始加载上似乎非常有效,但在向viewModel添加更多节点后,绑定似乎停止工作

这似乎比我感觉的要困难得多,这让我觉得我错过了什么

有人能帮忙解释一下吗

谢谢

杰森

JSFIDLE 我创建了一个JSFIDLE示例供我们在本次讨论中使用:

HTML 问题 我遇到的问题是将子节点文本框绑定到分层数据源中相应viewModel字段的displayValue属性。我尝试过许多不同的方法,但“某种程度上”有效的方法是通过:data bind=“value:treeData[#:item.parentIndex][#]。items[#:item.childIndex][displayValue]直接从模板绑定访问数组元素

请注意,添加第二个节点后,上述绑定不起作用。这就是问题所在。我同意代码是复杂的,这是问题的部分原因。。。我觉得有点不对劲。因此,要么kendo MVVM不支持直接绑定到嵌套数组元素,要么我做了一些完全错误的事情

更新输出 我更新了JSFIDLE并发布了输出以更好地说明问题。请注意,viewModel上的第二组子元素如何具有空白的displayValue属性,即使我在视图中更改了它们。在添加第一个节点后,由于某种原因绑定无法工作

新的JSFIDLE:

viewModel的打印输出
我觉得你的代码很复杂。你能解释一下你想实现什么吗,也许有一个更简单的方法。到目前为止,您的代码只显示一个级别的元素(父元素和3个子元素),因此不需要树。您使用树是因为在最终的实现中,这些子级可能有另一个具有相同结构的子级吗?为了更清楚一点,我更新了这个问题。感谢您的时间。此外,除了第一级之外,将不会有更多的子级。另外,请注意,此代码仅用于演示绑定的问题,这不是我使用的实际代码:)我刚刚隔离了绑定的问题。更新的JSFIDLE:
<script id="treeTemplate" type="text/x-kendo-template">
    <span>
        #: item.name #
        # if (!item.hasChilren) { #
            <input type = 'text' data-bind = "value: treeData[#: item.parentIndex #].items[#: item.childIndex #].displayValue"/> 
        # } #
    </span>
</script>

<div id="content">
    <div id="form">
        <label>Item Name:
            <input type="text" data-bind="value: form.itemName" />
        </label>
        <button data-bind="click: form.onAddItem">Add Item</button>
        <div class="console">
            <h2>Output:</h2>
            <div id="myConsole"/>
        </div>
    </div>
    <h2>TreeView</h2>
    <div data-template="treeTemplate" data-role="treeview" data-bind="source: treeData" />
</div>
(function ($) {
    var viewModel = kendo.observable({
        itemIndex: 0,
        form: {
            itemName: '',
            onAddItem: function (e) {
                e.preventDefault();

                var itemToAdd = {
                    name: viewModel.get('form.itemName'),
                    hasChilren: true,
                    items: (function () {
                        var children = [];
                        for (var i = 0; i < 3; i++) {
                            children.push({
                                name: viewModel.get('form.itemName') + '-child-' + i,
                                parentIndex: viewModel.get('itemIndex'),
                                childIndex: i,
                                displayValue: '',
                                hasChilren: false
                            });
                        }
                        return children;
                    })()
                }

                if (viewModel.get('treeData')) {
                    viewModel.get('treeData').push(itemToAdd);
                } else {
                    viewModel.set('treeData', kendo.observableHierarchy([itemToAdd]));
                }

                viewModel.set('form.itemName', '');
                viewModel.set('itemIndex', viewModel.get('itemIndex') + 1);
            }
        }
    });

    $(document).ready(function () {
        kendo.bind(document.body, viewModel);
        viewModel.bind('change', function (e) {
            console.log('viewModel changed!');
            var output = JSON.stringify(viewModel, undefined, 2);
            console.log('----------------------------------------------------');
            console.log(output);
            console.log('----------------------------------------------------');
            $("#myConsole").html("<pre>" + output + "</pre>");
        });
    });
})(jQuery);
* parentNode.name
--->* childNode.name [textbox bound to this node's displayValue property in viewModel]
--->* childNode.name [textbox bound to this node's displayValue property in viewModel]
--->* childNode.name [textbox bound to this node's displayValue property in viewModel]
--->* childNode.name [textbox bound to this node's displayValue property in viewModel]
{
  "itemIndex": 2,
  "form": {
    "itemName": ""
  },
  "treeData": [
    {
      "name": "a",
      "hasChilren": true,
      "items": [
        {
          "name": "a-child-0",
          "parentIndex": 0,
          "childIndex": 0,
          "displayValue": "1",
          "hasChilren": false,
          "items": [],
          "index": 0
        },
        {
          "name": "a-child-1",
          "parentIndex": 0,
          "childIndex": 1,
          "displayValue": "2",
          "hasChilren": false,
          "items": [],
          "index": 1
        },
        {
          "name": "a-child-2",
          "parentIndex": 0,
          "childIndex": 2,
          "displayValue": "3",
          "hasChilren": false,
          "items": [],
          "index": 2
        }
      ],
      "index": 0,
      "expanded": true
    },
    {
      "name": "b",
      "hasChilren": true,
      "items": [
        {
          "name": "b-child-0",
          "parentIndex": 1,
          "childIndex": 0,
          "displayValue": "",
          "hasChilren": false,
          "index": 0
        },
        {
          "name": "b-child-1",
          "parentIndex": 1,
          "childIndex": 1,
          "displayValue": "",
          "hasChilren": false,
          "index": 1,
          "selected": true
        },
        {
          "name": "b-child-2",
          "parentIndex": 1,
          "childIndex": 2,
          "displayValue": "",
          "hasChilren": false,
          "index": 2
        }
      ],
      "index": 1,
      "expanded": true
    }
  ]
}