locked
Item templates overlap in a listview when they are with varying height and width.

    Question

  • I am trying to get a listview in HTML 5 with templates having different height and width. I have used the http://code.msdn.microsoft.com/windowsapps/ListView-item-templates-7d74826f the scenario 4 in this sample. Below is my code

           <div id="lstview" data-win-control="WinJS.UI.ListView"></div>

    args.setPromise(WinJS.UI.processAll().then(function () { var listView = document.getElementById("lstview").winControl; listView.forceLayout(); listView.itemDataSource = dtaSrc.dataSource; listView.layout = WinJS.UI.GridLayout; listView.itemTemplate = templatingFunction; listView.groupInfo = { enableCellSpanning: true, cellWidth: 200, cellHeight: 200 }; }));

        function templatingFunction(itemPromise) {
            return itemPromise.then(function (item) {
    
                var mainDiv = document.createElement("div");
                if (item.data.title == "square tile")
                    WinJS.Utilities.addClass(mainDiv, "item-info");
                if (item.data.title == "Rectangle tile")
                    WinJS.Utilities.addClass(mainDiv, "rect-item");
                var h4Title = document.createElement("h4");
                WinJS.Utilities.addClass(h4Title, "item-title");
                h4Title.innerHTML = item.data.title;
                mainDiv.appendChild(h4Title);
    
                //Create the content and set the text in it
                var h6Content = document.createElement("img");
                WinJS.Utilities.addClass(h6Content, "item-img");
                h6Content.src = item.data.picuture;
                mainDiv.appendChild(h6Content);
    
                //Return the html for the given data
                return mainDiv;
    
            });

     
       I am not able to make out what I am missing in this. Please help me out
    • Edited by Ramya SJ Monday, July 30, 2012 1:07 PM
    Monday, July 30, 2012 1:05 PM

Answers

  • There are a couple of errors in your code.

    First, the groupInfo property is a function that's part of the GridLayout object, not the ListView itself. In your code you're assigning an object to a property of the listview, instead of assigning a function that returns that object to a property of the GridLayout. You also need to use new on the GridLayout object.

    Try this code instead:

    listView.layout = new WinJS.UI.GridLayout;

    listview.layout.groupInfo = function () {
        return
    {
            enableCellSpanning
    : true,
            cellWidth
    : 200,
            cellHeight
    : 200
            };
    }

    This is how you announce cell spanning to the GridLayout; otherwise it will go to its default behavior of applying the first item's dimensions to all the items, which is what you're seeing.

    .Kraig

    • Marked as answer by Ramya SJ Tuesday, July 31, 2012 4:38 AM
    Monday, July 30, 2012 5:46 PM

All replies

  • You can not have varying height items in a list view.

    -Jeff


    Jeff Sanders (MSFT)

    Monday, July 30, 2012 5:43 PM
    Moderator
  • There are a couple of errors in your code.

    First, the groupInfo property is a function that's part of the GridLayout object, not the ListView itself. In your code you're assigning an object to a property of the listview, instead of assigning a function that returns that object to a property of the GridLayout. You also need to use new on the GridLayout object.

    Try this code instead:

    listView.layout = new WinJS.UI.GridLayout;

    listview.layout.groupInfo = function () {
        return
    {
            enableCellSpanning
    : true,
            cellWidth
    : 200,
            cellHeight
    : 200
            };
    }

    This is how you announce cell spanning to the GridLayout; otherwise it will go to its default behavior of applying the first item's dimensions to all the items, which is what you're seeing.

    .Kraig

    • Marked as answer by Ramya SJ Tuesday, July 31, 2012 4:38 AM
    Monday, July 30, 2012 5:46 PM
  • Thanks for the reply that helped a lot
    Tuesday, July 31, 2012 4:39 AM
  • That's correct with the ListLayout--it only supports fixed-height items. GridLayout, on the other hand, supports cell spanning that allows for variable width and height both, as I explained.
    Tuesday, July 31, 2012 5:33 AM
  • Hi Kraig,

    not sure if this should be a separate question or part of this one. But i am doing the same as Regel_1 and i followed what was in a couple of the samples provided by Microsoft but i can't get the cell spanning to work. 

    EDIT:  I am on Win8 CP and VS2012 RC, tried updating the properties to your other post "In Consumer Preview those are multiSize, slotWidth, and slotHeight (the names will be changing in the next release, mind you)" With no luck :(

    When i add the following code that you mentioned in your post 

    listview.layout.groupInfo = function () {
        return 
    {
            enableCellSpanning
    : true,
            cellWidth
    : 200,
            cellHeight
    : 200
            };
    }

    The item-container width is set to zero and the height 240px.

    Here is the template code:

     <div class="headerTemplate" data-win-control="WinJS.Binding.Template">
            <p class="group-title win-type-x-large" data-win-bind="textContent: title; groupKey: key" 
                onclick="WinJS.Navigation.navigate('/pages/groupDetail/groupDetail.html', { groupKey: event.srcElement.groupKey })" role="link"></p>
        </div>
        <div class="itemtemplate" data-win-control="WinJS.Binding.Template">
             <div data-win-bind="className: spanClass;">
                <div data-win-bind=" className:backgroundClass;">
                   
                   <!-- <img class="item-image" src="#" data-win-bind="src: backgroundImage; alt: title" /> -->
                    <div class="item-overlay">
                        <h4 class="item-title" data-win-bind="textContent: title"></h4>
                        <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: subtitle"></h6>
                    </div>
                </div>
            </div>
        </div>
    
    
        <div class="productspage fragment">
            <header aria-label="Header content" role="banner">
                <button class="win-backbutton" aria-label="Back" disabled></button>
                <h1 class="titlearea win-type-ellipsis">
                    <span class="pagetitle">Welcome to products</span>
                </h1>
            </header>
            <section aria-label="Main content" role="main">
                <div class="groupeditemslist" aria-label="List of groups" data-win-control="WinJS.UI.ListView" data-win-options="{ selectionMode: 'none' }"></div>
            </section>
            <footer>
                 <div class="footer" data-win-control="WinJS.UI.HtmlControl" data-win-options="{uri: '/html/footer.html' }"></div>
            </footer>
    
        </div>

     Here is the js: 

    ready: function (element, options) {
                var listView = element.querySelector(".groupeditemslist").winControl;
                
                listView.forceLayout();
                listView.groupHeaderTemplate = element.querySelector(".headerTemplate");
                listView.itemTemplate = element.querySelector(".itemtemplate");
                listView.oniteminvoked = this.itemInvoked.bind(this);
    
                listView.itemDataSource = Data.items.dataSource;
                listView.groupDataSource = Data.groups.dataSource;
                listView.layout = new ui.GridLayout;//({ groupHeaderPosition: "top" });
                console.log("setting group info");
                listView.layout.groupInfo = function () {
                    console.log("group info");
                    return {
                        enableCellSpanning: true,
                        cellWidth: 150,
                        cellHeight: 150
                    };
                }
    
                console.log("cell spanning " + listView.layout.groupInfo);
                
                listView.element.focus();
    
            },

    Any help would be greatly appreciated!

    thanks,

    kle



    • Edited by kle.miller Tuesday, August 7, 2012 6:45 AM added extra information about windows and VS version.
    Tuesday, August 7, 2012 6:34 AM
  • Yes, as you can see the names of the properties in the groupInfo function changes from CP to RP. Also, cell spanning wasn't as reliable in CP like it is in RP. Since so much else has changed you should update to RP and develop against that and update to RTM as soon as that is available to developers, as we won't be providing ongoing support for the older previews.

    Wednesday, August 8, 2012 4:14 PM
  • Hey Kraig,

    I have a more complicated example where I am using nested listviews. So the itemTemplate of the outer list is a ListView itself, so the width of this item is really dynamic and there's no way to know the width before hand since the itemDataSource is async.

    And as you know, the ListView needs specific width and heights in order for it to render itself.

    Do you have any suggestions?

    THanks,

    Joe


    Joseph

    Tuesday, August 14, 2012 7:53 PM
  • Why isn't this in the documentation anywhere? So confusing.
    Tuesday, August 14, 2012 8:24 PM
  • To answer both of the last two questions: first, some of these intricacies only came online later in the product cycle and it takes time to get the documentation written and published, according to many different priorities. It's also helpful with these kinds of changes to follow the Win8 Developer Blog http://blogs.msdn.com/b/windowsappdev/ . Changes between CP, RP, and RTM are posted there. We also rely on some of the samples to fully document many such features. In this case, the HTML Listview Item Templates sample is your friend.

    With Joe's question, there is another property of GridLayout called itemInfo for this purpose. This is a function is given an itemID and returns an object of properties describing the exact size for each item (as well as column breaks). Scenario 5 of the sample above shows this; the properties in the object are named newColumn (a Boolean), itemWidth, and itemHeight. So you should be able to check the width of a dynamic item at runtime and return it through this function.

    .Kraig

    Tuesday, August 14, 2012 8:41 PM
  • Kraig,

    Thank you for your reply. This brings some hope. Is there any way you can provide me with a code snippet?

    I'm guessing this property should be set on the outer listview layout, whose items are of a dynamic dimensions nature.

    Thanks,

    Joe


    Joseph

    Tuesday, August 14, 2012 10:09 PM
  • Yes, set it on the outer listview, and in the function calculate the current sizes of the inner list controls.

    As for code, here's an example from modifications I made to the sample I linked earlier (which doesn't show itemInfo...I have a modified sample in my book's companion content. We'll be putting this out soon). With this, I change the reported item size based on its class, but it gives you the idea. Note that you always have to use groupInfo in conjunction with itemInfo.

    function itemInfo(index) {
        //getItem(index).data retrieves the array item from a WinJS.Binding.List
        var item = myCellSpanningData.getItem(index).data;
        var width, height;
    
        switch (item.type) {
            case "smallListIconTextItem":
                width = 145;
                height = 70;
                break;
    
            case "mediumListIconTextItem":
                width = 310;
                height = 70;
                break;
    
            case "largeListIconTextItem":
                width = 310;
                height = 160;
                break;
        }
    
        return {
            //newColumn: false,
            //To show column breaking, uncomment this line and comment out the one above
            newColumn: (index == 6 || index == 14),   //Break on items 7 and 15 (index is 6 and 14)
            itemWidth: width,
            itemHeight: height
        };
    }

    Tuesday, August 14, 2012 10:51 PM