When you do have a page that makes use of a ScrollView you can not use a ListView in it. It will result in strange presentation. For instance using this code:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
xmlns:i18n="clr-namespace:TenCate_App.Helpers;assembly=TenCate_App"
xmlns:mr="clr-namespace:MR.Gestures;assembly=MR.Gestures"
xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
x:Class="TenCate_App.Views.ProductPage" x:Name="ProductPageRef"
Title="{i18n:Translate ProductPage_Title}" ControlTemplate="{StaticResource PageTemplate}"
NavigationPage.BackButtonTitle="">
<ScrollView>
<Grid Padding="0">
<Grid.RowDefinitions>
<RowDefinition Height="90" />
<RowDefinition Height="35" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackLayout Grid.Row="2" Padding="0" BackgroundColor="White" VerticalOptions="FillAndExpand">
<Label Margin="10" Text="{Binding ProductItem.Name}" Style="{StaticResource NameLabelStyle}" />
<Label Margin="10" Text="{i18n:Translate ProductDescription}" Style="{StaticResource SectionLabelStyle}" />
<Label Margin="10,0,10,0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" LineBreakMode="WordWrap"
Text="{Binding ProductItem.Body}" Style="{StaticResource InfoLabelValueStyle}" />
<Label Margin="10,10,10,0" Text="{i18n:Translate ProductBenefits}" Style="{StaticResource SectionLabelStyle}" />
<ListView x:Name="lstFeaturess" VerticalOptions="FillAndExpand" Margin="0" HeightRequest="{Binding ProductItem.FeaturesHeight}"
SeparatorVisibility="None" ItemsSource="{Binding ProductItem.FeatureItems}" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="10,0,14,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" HeightRequest="12" HorizontalOptions="Start" Source="arrow_right_active.png" />
<Label Grid.Column="1" Text="{Binding Title}" Style="{StaticResource InfoLabelStyle}" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
will result in this presentation:
To be able to present a dynamic list we are going to use a custom Grid control where the rows are create dynamically.
The XAML of this new custom grid control looks like:
<?xml version="1.0" encoding="UTF-8"?>
<Grid xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TenCate_App.Views.DynamicGridView"
x:Name="DynamicGrid" RowSpacing="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
</Grid>
And the code behind:
using System.Collections.Generic;
using TenCate_App.Models;
using Xamarin.Forms;
namespace TenCate_App.Views
{
public partial class DynamicGridView : Grid
{
public DynamicGridView()
{
InitializeComponent();
}
public static readonly BindableProperty DynamicRowsProperty =
BindableProperty.Create(nameof(DynamicRows), typeof(List<Item>), typeof(DynamicGridView), null,
BindingMode.OneWay, null, OnDynamicRowsChanged);
private static void OnDynamicRowsChanged(BindableObject bindable, object oldvalue, object newvalue)
{
var control = (DynamicGridView)bindable;
if (control != null)
{
if (newvalue is List<Item> dynamicRows)
{
var rowNumber = -1;
Style imageStyle = Application.Current.Resources["ItemIconStyle"] as Style;
Style labelStyle = Application.Current.Resources["ItemLabelStyle"] as Style;
foreach (var dynamicRow in dynamicRows)
{
var image = new Image {Source = "arrow_right_active.png"};
image.Style = imageStyle;
var valueLabel = new Label { Text = dynamicRow.Title };
valueLabel.Style = labelStyle;
rowNumber++;
control.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
control.Children.Add(image, 0, rowNumber);
control.Children.Add(valueLabel, 1, rowNumber);
}
}
}
}
public List<Item> DynamicRows
{
get => (List<Item>)GetValue(DynamicRowsProperty);
set => SetValue(DynamicRowsProperty, value);
}
}
}
Now we are going to use this custom Grid control in our page withe the ScrollView:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
xmlns:i18n="clr-namespace:TenCate_App.Helpers;assembly=TenCate_App"
xmlns:localCtrl="clr-namespace:TenCate_App.Views;assembly=TenCate_App"
xmlns:mr="clr-namespace:MR.Gestures;assembly=MR.Gestures"
xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
x:Class="TenCate_App.Views.ProductPage" x:Name="ProductPageRef"
Title="{i18n:Translate ProductPage_Title}" ControlTemplate="{StaticResource PageTemplate}"
NavigationPage.BackButtonTitle="">
<ScrollView>
<Grid Padding="0">
<Grid.RowDefinitions>
<RowDefinition Height="90" />
<RowDefinition Height="35" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackLayout Grid.Row="2" Padding="0" BackgroundColor="White" VerticalOptions="FillAndExpand">
<Label Margin="10" Text="{Binding ProductItem.Name}" Style="{StaticResource NameLabelStyle}" />
<Label Margin="10" Text="{i18n:Translate ProductDescription}" Style="{StaticResource SectionLabelStyle}" />
<Label Margin="10,0,10,0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" LineBreakMode="WordWrap"
Text="{Binding ProductItem.Body}" Style="{StaticResource InfoLabelValueStyle}" />
<Label Margin="10,10,10,0" Text="{i18n:Translate ProductBenefits}" Style="{StaticResource SectionLabelStyle}" />
<localCtrl:DynamicGridView DynamicRows="{Binding ProductItem.FeatureItems}"></localCtrl:DynamicGridView>
And this will be the presentation: