Alessandro Caliaro
Alessandro Caliaro

Reputation: 5768

Xamarin.Forms ListView. Can I know the height of each row?

I have a ListView with HasUnevenRows = true.

I bind ItemSource to an ObservableCollection.

This Collection fill the ListViews with some rows. Each row has a different height because the text is different from row to row.

I would like to know if I can know which is the Height of each row.

Thanks Alessandro

            IEnumerable<PropertyInfo> pInfos = (ListViewPrivacy as ItemsView<Cell>).GetType().GetRuntimeProperties();
            var templatedItems = pInfos.FirstOrDefault(info => info.Name == "TemplatedItems");
            if (templatedItems != null)
            {
                var cells = templatedItems.GetValue(ListViewPrivacy);
                foreach (ViewCell cell in cells as Xamarin.Forms.ITemplatedItemsList<Xamarin.Forms.Cell>)
                {

                    if (cell.BindingContext != null)
                    {

                        System.Diagnostics.Debug.WriteLine("CellHeight = " + cell.Height + " - " + cell.RenderHeight + " " + cell.View.Height + " - " + cell.View.HeightRequest + " - " + cell.View.MinimumHeightRequest + " - " );
                        Grid grid = (Grid)cell.View;
                        System.Diagnostics.Debug.WriteLine("Height = " +  grid.Height.ToString() + " - " + grid.HeightRequest + " - " + grid.MinimumHeightRequest);


                    }
                }
            }

I have tried with a code like this but I have always "-1" in each property

Upvotes: 2

Views: 705

Answers (2)

Marlon Adarme
Marlon Adarme

Reputation: 375

I'd like to share my solution based on Alessandro's answer, but using FlowListView. I needed to set the FlowListView HeightRequest, because there was a huge empty space after the list.

XAML

<flv:FlowListView
     FlowColumnCount="1"
     FlowItemsSource="{Binding Coverages}"
     SeparatorVisibility="None"
     VerticalScrollBarVisibility="Never"
     x:Name="listConverages"
     HasUnevenRows="True">
     <flv:FlowListView.FlowColumnTemplate>
         <DataTemplate>
             <StackLayout
                  SizeChanged="StackLayout_SizeChanged">
             </StackLayout>
         </DataTemplate>
     </flv:FlowListView.FlowColumnTemplate>
</flv:FlowListView>

Code behind

private Dictionary<Guid, double> itemsHeight = new Dictionary<Guid, double>();
private void StackLayout_SizeChanged(object sender, EventArgs e)
{
    StackLayout stackLayout = (StackLayout)sender;

    if (!itemsHeight.ContainsKey(stackLayout.Id))
        itemsHeight.Add(stackLayout.Id, stackLayout.Height);
    else
        itemsHeight[stackLayout.Id] = stackLayout.Height;

    listConverages.HeightRequest = itemsHeight.Sum(x => x.Value);
}

NOTE: if you have bottom or top margins, add them to the value before adding the item to the dictionary

Upvotes: 1

Alessandro Caliaro
Alessandro Caliaro

Reputation: 5768

Ok, I have found this solution.

            <ViewCell>
                <Grid
                    SizeChanged="ViewCell_SizeChanged"

this is ViewCell_SizeChanged:

    double totalHeight = 0;
    int counter = 0;

    private void ViewCell_SizeChanged(object sender, EventArgs e)
    {

        if(sender is Grid)
        {
            Grid grid = (Grid)sender;

            totalHeight += grid.Height;
            totalHeight += grid.Margin.Top;
            totalHeight += grid.Margin.Bottom;

            if(++counter == ((MyViewModel)this.BindingContext).MyObservableCollection.Count)
                Device.BeginInvokeOnMainThread(() => MyListView.HeightRequest = totalHeight);
        }
    }

When the ViewCell is filled with data, the Grid is resized so the ViewCell_SizeChanged event is rised. There I have the current Grid.Height and Margin valorized. When I have reached the total number of Items, I have the exact height of all Grids in the ListView

Upvotes: 3

Related Questions