嵌套ListView或嵌套转发器

时间:2015-08-07 20:25:59

标签: winjs win-universal-app

我正在尝试使用WinJS 4.0创建嵌套转发器或嵌套列表视图,但我无法弄清楚如何绑定内部列表视图/转发器的数据源。

以下是我尝试做的一个示例(注意控件可能是Repeater,我更喜欢):

HTML:

<div id="myList" data-win-control="WinJS.UI.ListView">
        <span data-win-bind="innerText: title"></span>          
        <div data-win-control="WinJS.UI.ListView">
        <span data-win-bind="innerText: name"></span>            
    </div>
</div>

JS:

var myList = element.querySelector('#myList).winControl;
var myData = [
      {
          title: "line 1",
          items: [
              {name: "item 1.1"},
              {name: "item 1.2"}
          ]
      },
      {
          title: "line 2",
          items: [
              {name: "item 2.1"},
              {name: "item 2.2"}
          ]
      }  
    ];
   myList.data = new WinJS.Binding.List(myData);

当我尝试这个时,内部列表没有任何渲染。我试图尝试使用这个答案Nested Repeaters Using Table Tags和这个WinJS: Nested ListViews,但我似乎仍然遇到同样的问题,希望它不那么复杂(比如KnockOut)。

我知道有人提到WinJS不支持嵌套的ListViews,但这似乎是在几年前,我希望这仍然不是问题。

更新

由于Kraig的回答,我能够让嵌套的中继器正常工作。这是我的代码:

HTML:

<div id="myTemplate" data-win-control="WinJS.Binding.Template">
   <div
      <span>Bucket:</span><span data-win-bind="innerText: name"></span>
      <span>Amount:</span><input type="text" data-win-bind="value: amount" />
      <button class="removeBucket">X</button>
      <div id="bucketItems" data-win-control="WinJS.UI.Repeater" 
         data-win-options="{template: select('#myTemplate')}" 
         data-win-bind="winControl.data: lineItems">
      </div>
   </div>
</div>
<div id="budgetBuckets" data-win-control="WinJS.UI.Repeater"
   data-win-options="{data: Data.buckets,template: select('#myTemplate')}">
</div>

JS :(在“use strict”声明之后)

WinJS.Namespace.define("Data", {
        buckets: new WinJS.Binding.List([
            {
                name: "A",
                amount: 5,
                lineItems: new WinJS.Binding.List( [
                        { name: 'test item1', amount: 50 },
                        { name: 'test item2', amount: 25 }
                    ]
                )
            }
        ])
    })

*请注意,这回答了我的部分问题,但是,我真的希望在回购调用之后完成所有操作并以编程方式设置转发器数据源。我将继续努力,如果我得到它,我会将其作为接受的答案发布。

2 个答案:

答案 0 :(得分:2)

Windows 8.1的HTML Repeater control sample在方案6中有一个带嵌套Repeater的示例,在这种情况下,Repeater是通过Template控件创建的。这是一个很好的起点。 (我在Programming Windows Store Apps with HTML, CSS, and JavaScript, 2nd Edition的第7章讨论了这个样本,从第372页开始,或374讨论了嵌套部分。)

仍然可以使用WinJS 4,但我还没有尝试过。

答案 1 :(得分:1)

好的,所以我必须对Kraig给予很多赞誉,因为他让我找到了正确的方法来解决这个问题,所引用的书Programming Windows Store Apps with HTML, CSS, and JavaScript, 2nd Edition非常棒。

最初的问题是没有正确使用模板(在data-win-bind属性中使用花括号),没有正确构建我的HTML而没有将子列表设置为WinJS.Binding.List数据源。下面是在仅从代码绑定数据时创建嵌套转发器的最终工作代码结构:

<强> HTML:

这是子列表的模板。它看起来很相似,但我计划添加更多东西,所以我希望它分开而不是书中引用的递归。请注意,模板控制声明后的内部div对我来说非常重要。

<div id="bucketItemTemplate" data-win-control="WinJS.Binding.Template">
   <div>
      <span>Description:</span>
      <span data-win-bind="innerText: description"></span>
      <span>Amount:</span>
      <input type="text" data-win-bind="value: amount" />
      <button class="removeBucketItem">X</button>
   </div>
</div>

这是列表的主要转发器模板。请注意,模板控制声明后的内部div对我来说很重要。另一个关键点是对子列表的属性名称使用“winControl.data”属性。

<div id="bucketTemplate" data-win-control="WinJS.Binding.Template">
   <div>
      <span>Bucket:</span>
      <span data-win-bind="innerText: bucket"></span>
      <span>Amount:</span>
      <input type="text" data-win-bind="value: amount" />
      <button class="removeBucket">X</button>
      <div id="bucketItems" data-win-control="WinJS.UI.Repeater" 
         data-win-options="{template: select('#bucketItemTemplate')}" 
         data-win-bind="winControl.data: lineItems">
      </div>
   </div>
</div>

这是嵌套转发器的主要控制元素,它非常基本。

<div id="budgetBuckets" data-win-control="WinJS.UI.Repeater" 
   data-win-options="{template: select('#bucketTemplate')}">
</div>

JavaScript:

JavaScript归结为几个简单的步骤:

  1. 获取winControl

    var bucketsControl = element.querySelector('#budgetBuckets').winControl;

  2. 循环使用元素并将子列表放入绑定列表 - 这里的数据已经组成,但很容易来自回购:

    var bucketsData = selectedBudget.buckets; for (var i = 0; i < bucketsData.length; i++) { bucketsData[i].lineItems = new WinJS.Binding.List([{ description: i, amount: i * 10 }]); }

  3. 然后最终将整个数据转换为绑定列表并将其设置为winControl的“data”属性。

    bucketsControl.data = new WinJS.Binding.List(bucketsData);

  4. *请注意,为了清楚起见,这是整个JavaScript文件。

    (function () {
        "use strict";
        var nav = WinJS.Navigation;
    
        WinJS.UI.Pages.define("/pages/budget/budget.html", {
            // This function is called whenever a user navigates to this page. It
            // populates the page elements with the app's data.
    
            ready: function (element, options) {
                // TODO: Initialize the page here.
                var bindableBuckets;
                require(['repository'], function (repo) {
                    //we can setup our save button here
                    var appBar = document.getElementById('appBarBudget').winControl;
                    appBar.getCommandById('cmdSave').addEventListener('click', function () {                    
                        //do save work
                    }, false);
                    repo.getBudgets(nav.state.budgetSelectedIndex).done(function (selectedBudget) {
                        var budgetContainer = element.querySelector('#budgetContainer');
                        WinJS.Binding.processAll(budgetContainer, selectedBudget);
                        var bucketsControl = element.querySelector('#budgetBuckets').winControl;
                        var bucketsData = selectedBudget.buckets;
                        for (var i = 0; i < bucketsData.length; i++)
                        {
                            bucketsData[i].lineItems = new WinJS.Binding.List([{ description: i, amount: i * 10 }]);
                        }
                        bucketsControl.data = new WinJS.Binding.List(bucketsData);
                    });
    
                });
                WinJS.UI.processAll();
    
            }
        });
    })();