WinJS.UI.ListView customize list item content?

2020-06-28 16:17发布

I'm working on a Javascript based Windows 8 Metro App. It uses WinJS.UI.ListView to display a 1 column list of items. I don't know much beyond what was said in the documentation: http://msdn.microsoft.com/en-us/library/windows/apps/br211837.aspx .

How do I customize the list item content, based on the data source? Is there a callback function available, so that for each list item, I get to show/hide certain HTML tags, based on the variable of the corresponding object in the data array?

Like the arrangement in the Examples section of this MSDN documentation, how do I show/hide the img tag based on whether picture exists?

On top of that, how do I have variable list item height? Each of my list item will have different height (actually only 2 different heights across all items), based on the show/hide function mentioned above. How to implement this behavior?

Thank you.

1条回答
爷、活的狠高调
2楼-- · 2020-06-28 16:47

The list layout in WinJS.UI.ListView does not support items of different heights; it has to be one specific height. If you need that layout, you are going to have to create it yourself. Depending on your data source & number of items this is either trivial, or hard. :)

That stated:

  • The listview does support different templates for each item. The itemTemplate property allows you to supply a function. The details are here
  • The grid layout does support different sized items, based on some properties and calculations. Details here, at the end

If you have small datasets (<50), then you can just dynamically create the elements yourself, and use the natural flow of child divs to stack your elements one-after the other. The seeds of this solution can be found in my answer here.

Let me expand up on the example control, based on a "Blank" WWA Project in VS

Add this code to your default.js:

WinJS.Namespace.define("Samples", {
    ItemsControl: WinJS.Class.define(function (element, options) {
        this.domElement = element;
        WinJS.UI.setOptions(this, options);
    }, {
        domElement: null,
        _dataSource: null,
        dataSource: {
            get: function () {
                return this._dataSource;
            },
            set: function (v) {
                this._dataSource = v;
                this._renderItems(v);
            }
        },
        pickTemplate: function (item) {
            // The tempalte is found in the WinJS.Binding.Template instances that are
            // in default.html. They have ID attributes on them. We're going to pick
            // which one we want by setting the ID we're looking for, and then getting
            // that element from the DOM and returning the winControl
            var templateId = "template1"
            if (item.isType2) {
                // Because this is "isType2", we're going to use the other template
                templateId = "template2";
            }

            return document.getElementById(templateId).winControl;
        },
        _renderItems: function (source) {
            // This function renders all the items, thus when you set the datasource, and
            // expect it to render items, you probably would like all your items to replace
            // any existing items.
            WinJS.Utilities.empty(this.domElement);
            source.forEach(function (item) {
                var newElement = document.createElement("div");
                this.domElement.appendChild(newElement);

                this.pickTemplate(item).render(item, newElement);
            }.bind(this));
        }
    }),
});

function makeContent() {
    var data = [
        { label: "First", },
        { label: "Second", },
        { label: "Third", isType2: true },
        { label: "Fourth", isType2: true },
        { label: "Fifth", },
        { label: "Sixth", isType2: true }
    ];

    var control = document.getElementById("itemsControl").winControl;

    control.dataSource = data;
}

And replace the content of body with:

<div data-win-control="WinJS.Binding.Template"
    id="template1">
    <div class="type1"
        data-win-bind="textContent: label"></div>
</div>

<div data-win-control="WinJS.Binding.Template"
    id="template2">
    <div class="type2"
        data-win-bind="textContent: label"></div>
</div>
<button onclick="makeContent()">Make Content</button>
<div id="itemsControl"
    data-win-control="Samples.ItemsControl">

</div>

Finally, in the default.css:

    .type1 {
        background-color: green;
        height: 50px;
        width: 100px;
    }

    .type2 {
        background-color: red;
        height: 100px;
        width: 100px;
    }
查看更多
登录 后发表回答