Reputation: 5768
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
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
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