0

A list of UIElements with the same height are added to a WrapPanel, and the XAML is

<Grid>
    <ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled">
        <ListView.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel />
            </ItemsPanelTemplate>
        </ListView.ItemsPanel>
    </ListView >
</Grid>

When run it looks like this

enter image description here

In order to get the item count of the first row, I tried to calculate the coordinates (relative to the listview) of each item's upper-left corner, by comparing each item's vertical offset with the first item, I can get the item count of the first row.

But the code can easily break if items have different height.

ListView listView = (sender as ListView);
if (listView.Items.Count > 0)
{
    UIElement firstItem = ((listView.Items)[0] as UIElement);
    double y = firstItem.TranslatePoint(new Point(0, 0), listView).Y; 

    int counter = 0;
    foreach (UIElement item in listView.Items)
    {
        if ((item.TranslatePoint(new Point(0, 0), listView).Y != y))
        {
            break;
        }
        counter++;
    }
}

What is the correct way to do this?

har07
  • 88,338
  • 12
  • 84
  • 137
kennyzx
  • 12,845
  • 6
  • 39
  • 83
  • The screenshot in the post is [link](http://i.stack.imgur.com/EhTHK.png), Sorry I have trouble editting my post... – kennyzx Jan 15 '14 at 09:56
  • And the code will of course fail if the items aren't UIElements. You should at least use `ListView.ItemContainerGenerator.ContainerFromItem`. – Clemens Jan 15 '14 at 10:13
  • 3
    And why not just check if the X value of the current item's position is less than or equal to that of the previous one. That would be an indicator that wrapping had occured. – Clemens Jan 15 '14 at 10:18
  • @Clemens Yes! That becomes obvious, checking the X value, great! But I had never thought of that, I was looking for a magic attached property like WrapPanel.Row that can give me the answer. – kennyzx Jan 15 '14 at 10:53
  • @Clemens Could you post it as an answer so I can accept it? thanks – kennyzx Jan 15 '14 at 10:54

1 Answers1

2

This method should get the job done:

private static int GetItemsInFirstRow(ItemsControl itemsControl)
{
    double previousX = -1;
    int itemIndex;

    for (itemIndex = 0; itemIndex < itemsControl.Items.Count; itemIndex++)
    {
        var container = (UIElement)itemsControl.ItemContainerGenerator
                                                .ContainerFromIndex(itemIndex);

        var x = container.TranslatePoint(new Point(), itemsControl).X;

        if (x <= previousX)
        {
            break;
        }

        previousX = x;
    }

    return itemIndex;
}
Clemens
  • 123,504
  • 12
  • 155
  • 268