locked
ListView: Items not being placed horizontally first. RRS feed

  • Question

  • Have a simple ListView right now with some 10 divs of the same size (screenshot below), they don't float or anything special. In the screenshot you see three coloured boxes, these are the first three of 10 divs. I expect these three to be along the top, 1 2 3 4 5. But it looks like the top row will have items 1 3 5 7 9 and row 2 will have 2 4 6 8 10. Is there some way to force ListViews to push horizontal first then go to the next row? Which I thought was the default. Code is below image.

     

     

    <div id="CategoryListView" data-win-control="WinJS.UI.ListView" data-win-options="{selectionMode: 'none'}" style="width:1110px;height:355px;">
    
       <div class="category-box category-bg-microsoftproducts"></div>  <--  Dark Blue Box
    <div class="category-box category-bg-internallob"></div> <-- Light blue box
    <div class="category-box category-bg-3rdpartyproducts"></div> <-- Orangy box
    <div class="category-box"></div> <div class="category-box"></div> <div class="category-box"></div> <div class="category-box"></div> <div class="category-box"></div> <div class="category-box"></div> <div class="category-box"></div> </div>

    Wednesday, January 25, 2012 11:08 PM

All replies

  • Hi H,

    The ListView in the GridView layout mode is designed to work just as you have specified.  Imagine if there were 400 Items in your list.  You would be displaying the first 10 items using this control.  You would scroll to horizontally to see the items further down in your list.

    If you wish to have a different layout (specifically in your case only ten items and arranged differently, you can certainly accomplish this using divs and not the ListView.

    -Jeff


    Jeff Sanders (MSFT)
    Thursday, January 26, 2012 4:08 PM
    Moderator
  • But isn't the ListView supposed to lay out horizontally first? Especially in the scenario with 400 items.

    I expect this with mine:

    1  2  3  4  5

    6  7  8  9  10

     

    Instead I'm getting this:

    1  3  5  7  9

    2  4  6  8  10

     

    In the "400" scenario I would get this?:

    1      80      160      240       320

    2      81      161      241       321

    3      82      162      241       322

    Thursday, January 26, 2012 4:14 PM
  • Hi H,

    In the 400 scenario using the GridView layout you would get:

    1 3 5 7 9

    2 4 6 8 10

    and when you scroll to the right you would get:

    11 13 15 17 19

    12 14 16 18 20

    Does that make it clearer?

    -Jeff


    Jeff Sanders (MSFT)
    Thursday, January 26, 2012 4:17 PM
    Moderator
  • Sounds good to me, cheerz.

     

    Might sound like something for the feature request forum, but setting the layout on a Listview to have horizontal:'false' would seem like something that would fix my scenario. Having the ListView as vertical would thus lay items down the opposite, horizontal first.

    • Proposed as answer by JohanBarnard Thursday, October 18, 2012 9:48 AM
    Thursday, January 26, 2012 4:31 PM
  • It is kind of odd to me that your code listed would show the layout you shared.

    A list view should not show the items horizontally by default.

    A straight ListView or one using the default layout: data-win-options="{layout: {type: WinJS.UI.ListLayout}}"  would just list the items vertically and give you a scroll bar for items that did not fit in the view.  If you specify grid layout: data-win-options="{layout: {type: WinJS.UI.GridViewLayout}}" I would expect the layout you showed in the post.

    Regardless, the two row layout with items 1-n/2 on the top row and then n/2+1 - n on the next row is not supported.  Wouldn't that seem a strange UI experience to you?  Maybe I do not fully understand what you are trying to accomplish?

    -Jeff

     

     


    Jeff Sanders (MSFT)
    Thursday, January 26, 2012 4:39 PM
    Moderator
  • I think you've defined it like they have in the ListView Quickstart just fine: http://msdn.microsoft.com/en-us/library/windows/apps/hh465496.aspx

    My thinking was that the ListView is the equivalent of the Silverlight WrapPanel. Where you can add 100x100 divs to it, and it would stack them horizontally until there is no more room left, then start on the next row. I don't think there is a WinJS equivalent then if the ListView, and I half expect there to be an itemLayout: 'horizontal' kind of feature, where you could my output of 1|2|3|4|5 on the first row, and 6|7|8|9|10 on the second.

    Thursday, January 26, 2012 5:05 PM
  • I understand.  No the ListView control will not give you the WrapPanel behavior out of the box.  You can accomplish this with other HTML and CSS style elements however.  How many items would your display typically have and is the count and content dynamic?  Would it perhaps be better served by adding the HTML dynamically and styling it with something like a flex box or Grid?

    -Jeff


    Jeff Sanders (MSFT)
    Thursday, January 26, 2012 6:44 PM
    Moderator
  • Well, if the ListView can't populate items horizontally, then vertically, and the only way it lays things out is vertically then horizontally, I guess FlexBox is the only thing to use.

    Now the other issue with using -ms-box is you don't get the built in pointerUp/pointerDown animations. And if I have to add these manually, which is easy, will there be a performance hit? If there's 400 items in the flexbox? 1000? Or would the performance be the same as a ListView with these attached animations.

    p.s. Flexbox has a "-ms-box-direction". It seems that the ListView could also use a direction property to do as I ask, because I won't be the only one that wants the 1|2|3|4|5 across.

    Cheers

    Thursday, January 26, 2012 7:22 PM
  • I know this is an old post... but I am having the same problem (and have already created a topic about it). For e-learning apps like mine, you definitely need the ability to show your content in a specific order (think about teaching SENTENCE building to kids for example...) In this case I'm doing a simple Alphabet app - and I need

    ABCD
    EFGH

    Right now, the default is:

    ACEG
    BDFH

    And since I'm completely new to  JavaScript/HTML5 dev (coming from Actionscript...) - I'm trying to make due with the lovely templates that come with Visual Studio Express 2012. So since the GridView template is already pretty perfect for my needs, it would be awesome to just mildly tweak this, rather than having to scrap the GridView completely and all the associated code - to add a FlexBox which right now I have no idea how to connect to the data, the functions, etc.  Not saying I can't do it - but it will take me a lot longer than if I just had a nice switch to tell the GridView to populate the data horizontally rather than vertically!

    Monday, August 27, 2012 5:43 PM
  • Hi Stacey,

    The nature of the grid layout is horizontal scrolling so no, there is not easy way to do this using the ListView control

    -Jeff


    Jeff Sanders (MSFT)

    Monday, August 27, 2012 5:45 PM
    Moderator
  • Thanks for the quick reply.

    So am I left with FlexBox as the best alternative? I don't want to go against Metro guidelines/principles and so some kind of fixed layout of 2 rows, which wouldn't reorganize properly when you resize the app.

    Monday, August 27, 2012 6:29 PM
  • You will need to determine what you need to do based on your app requirements.  The listview in grid layout is best for an unknown number of items that can potentially scroll horizontally.  Given what you have told me, I think Flex box or -ms-grid would meet your needs.

    -Jeff


    Jeff Sanders (MSFT)

    Monday, August 27, 2012 6:31 PM
    Moderator
  • You can use the ListView control and get the result you want. You have to rearrange the data from your data source to achieve your desired view order.

    Example:

    Original data order: A B C D E F G H
    This will be show as this in the ListView:
    A C E G
    B D F H

    Custom data order: A E B F C G D H
    This will be shown as this is the ListView:
    A B C D
    E F G H

    Here is how you can reorder your data in JS:

    var reorderedData = [];
        var originalData = getDataFromMySource();
        var half = originalData.length / 2; // We assume that the ListView has only two rows.
        
        for (var i = 0; i < half; i++) {
            var firstRowItem = originalData[i];
            var secondRowItem = originalData[i + half];
    
            reorderedData.push(firstRowItem);
            reorderedData.push(secondRowItem);
        }

    • Edited by Aratys Tuesday, August 28, 2012 10:07 AM Added JS code example.
    • Proposed as answer by Aratys Tuesday, August 28, 2012 10:08 AM
    Tuesday, August 28, 2012 8:26 AM
  • This will not work on all screen resolutions.  When the grid view expands to 3 rows this breaks ala : ; // We assume that the ListView has only two rows.

    Jeff Sanders (MSFT)

    Tuesday, August 28, 2012 12:13 PM
    Moderator
  • One solution to that is to set the 'maxRow' property in the ListVuew to '2'.

    listView.layout = new ui.GridLayout({ maxRows: "2" });
    Link to documentation: http://msdn.microsoft.com/en-us/library/windows/apps/br211750.aspx
    • Edited by Aratys Tuesday, August 28, 2012 2:19 PM Added link to documentation.
    • Proposed as answer by staceyreiman Thursday, August 30, 2012 5:05 PM
    Tuesday, August 28, 2012 1:27 PM
  • Thanks very much for the help!

    As I'm super new to Metro dev, I'm wondering though how this will handle all of the different screen changes that your app has to be able to accommodate (snap view, rotated tablet, etc). I realize that I can use different data sets, so maybe that answers the question - I'll definitely try this out, as I've already wasted 2 days on this!

    I did already lay the alphabet out in a FlexBox - which looks great, but frankly adding all of the interactivity and functions to connect the FlexBox to data.js, the transitions, mouse events, and detail pages - would take me LONGER than just using the ListView template code that already has all of that built in.

    Thanks to Aratys and jpsanders for the help here, I'll try to post my solution and a screenshot once its done.

    Tuesday, August 28, 2012 8:24 PM
  • I wonder if I might be better of using a JavaScript grid like this one?

    https://github.com/bramstein/jlayout

    Tuesday, August 28, 2012 9:13 PM
  • Ok after monkeying around with FlexBox for a good while - your solution is in fact much better.

    I will just alter the data sets and maxRows for different views. The grid template provided by Microsoft has so much useful code that trying to rewire the FlexBox from scratch proved a lot harder than using your data re-ordering. In particular as a newbie trying to rework the navigation from my patchwork solution ended up a nightmare. Then I pasted your few lines of code into the standard grid app template, and wa-lah it worked perfect.

    Thursday, August 30, 2012 5:08 PM
  • Stacey,

    Just one thing to be aware of.  Test your application in the simulator.  Try all the different resolutions in there from the smallest to the largest (or use that feature in Blend).  Then ensure you try snap view and rotate the screen to portrait view.  That will ensure your display looks good on all those different form factors.

    -Jeff


    Jeff Sanders (MSFT)

    Thursday, August 30, 2012 5:11 PM
    Moderator
  • Thanks Jeff, I figured I'd have to do this as this solution is certainly not ideal!
    Thursday, August 30, 2012 7:06 PM
  • Hello Jeff  - I am a little stumped about how to change out my data array for the different views like snapped, etc. I'm using the stock template for a Grid app provided with Blend for Visual Studio - and have found the logic for doing this is present in the groupedItems.js file - here is the snapped view function:

           if (viewState === appViewState.snapped) {
                    listView.itemDataSource = Data.groups.dataSource;
                    listView.groupDataSource = null; 
                    listView.layout = new ui.ListLayout()
                }

    I've already reordered this data using the function provided above by Aratys, for a 4 row layout, 2 row layout, original data for a 1 row layout, etc -  but I'm not sure how to actually access these new arrays. The problem isn't so much with the groupedItems.js - I know I can change the dataSource in this file like this:

     listView.itemDataSource = Data.groups.originalItems; 

    But it is in the data.js file where my trouble is, as I can only return 1 set of data at a time for the group -

        // This function returns a WinJS.Binding.List containing only the items
        // that belong to the provided group.
        function getItemsFromGroup(group) {
            return list.createFiltered(function (item) { return item.group.key === group.key; });
        }

    I'm not sure how to allow for 3 or 4 different arrays to be used for the same group...

    Sorry this assumes you are already familiar with the setup of the data.js in the GridView template - and I may not even be asking the right questions here, but right now it seems that re-ordering the data for each view is a lot better solution than trying to rewire the whole app to work with the FlexBox - although I may be wrong on that one. I've searched high and low on the internet and cannot find any samples of somebody who has replaced the standard GridView with a FlexBox in order to get their data flowing horizontally in a JavaScript WinRT app. 

     

     

    Saturday, September 1, 2012 8:32 PM
  • Ah and I know you've asked before if having the data presented horizontally wouldn't be terrible for user experience, but if you think about how educational apps are layed out - teaching things like math, days of the week, calendars, the alphabet, reading, etc - you very often need the data to be read from left to right. Nobody is trying to wreck the user experience just because they need a grid of data that reads left to right rather than up and down :)
    • Edited by staceyreiman Saturday, September 1, 2012 8:39 PM
    Saturday, September 1, 2012 8:37 PM
  • RE: "I'm not sure how to allow for 3 or 4 different arrays to be used for the same group..."

    Can you give an example of what your data is and how you are grouping it?  In general if you are grouping data, it should all be in the same array to begin with.  The code behind this is simply iterating over your list of data and the functions define the group that your data would fall into.

    -Jeff


    Jeff Sanders (MSFT)

    Tuesday, September 4, 2012 12:16 PM
    Moderator
  •   I know this is an old - old topic. But anyone, or Stacey did you find any solution? Were you able to complete your app? I'm like you - super new to all these app dev things and starting out with this same ABCD app like thing. (As I've toddler too...)..

    Hope to hear something...

    thanks

    Monday, May 20, 2013 8:25 PM
  • @SonalMac - Best thing to do is to use a WrapPanel I think with an ItemsControl, as it places things onto itself horizontally. But you need to do some size calculations for it's width/height and stuff like that if you want it to grow horizontally.

    Edit: The WrapPanel to use is in the WinRTXamlToolkit, you can find on web and NuGet.

    • Edited by Harlequin Tuesday, May 28, 2013 2:12 PM edit
    Tuesday, May 28, 2013 2:08 PM