在 Xamarin Forms 中实现 bottom sheet 时未显示最后一个 ListView 项目

Last ListView Items not showing when implementing bottom sheet in Xamarin Forms

我尝试为我的 Xamarin 表单应用实现底部 sheet。我已经使用包括 nugets 在内的几种方法实现了。在我的主视图中,我有一个 ListView。在底部 sheet 普通框架和标签。我的问题是最后一两个项目在几乎所有选项的 ListView 中没有显示或部分显示。

    <?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:yummy="clr-namespace:Xamarin.Forms.PancakeView;assembly=Xamarin.Forms.PancakeView" 
                 x:Class="RSMapp.Views.RSMview">
        <ContentPage.ToolbarItems>
            <ToolbarItem Name="MenuItem" Command="{Binding filterCommand}" Order="Primary" Icon="filter.png" Text="" Priority="0" IsEnabled="{Binding IsEnabled}" />
        </ContentPage.ToolbarItems>
        <ContentPage.Content>
    
            <RelativeLayout>
    
                <StackLayout BackgroundColor="#d4d4d4" x:Name="mainView" Orientation="Vertical" HorizontalOptions="FillAndExpand" VerticalOptions="StartAndExpand">
    
                    <Grid RowSpacing="0">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="70"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
    
                        <yummy:PancakeView HeightRequest="55" BackgroundColor="{Binding mainBgColor}" Padding="10" HorizontalOptions="FillAndExpand" x:Name="dropdownLayout" CornerRadius="0,0,15,15" VerticalOptions="CenterAndExpand" Grid.Row="0">
    
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*"/>
                                    <ColumnDefinition Width="AUTO"/>
                                </Grid.ColumnDefinitions>
    
                                <Frame IsVisible="{Binding isMonthVisible}" HasShadow="{OnPlatform Android=true, iOS=false}" HorizontalOptions="FillAndExpand" BackgroundColor="WhiteSmoke" Padding="10,0,10,0" CornerRadius="15" Grid.Column="0">
    
                                    <Picker                            
                                            Title="{Binding SelectedItem.mName}"
                                            IsVisible="{Binding isMonthVisible}"   
                                            TitleColor="Black"   
                                            VerticalTextAlignment="Center"
                                            Margin="0,0,20,0"
                                            Focused="Picker_Focused"
                                            TextColor="#565656"                      
                                            ItemsSource="{Binding MyList}"
                                            SelectedItem="{Binding SelectedItem}"
                                            ItemDisplayBinding="{Binding mName}" />
    
                                </Frame>
    
                                <StackLayout WidthRequest="60" IsVisible="{Binding extraBtnVisible}" VerticalOptions="Center" HorizontalOptions="Center" Grid.Column="1">
                                    <ImageButton HeightRequest="50" WidthRequest="30" Command="{Binding regionClassCommand}" VerticalOptions="Center" IsVisible="{Binding extraBtnVisible}" BackgroundColor="#F44336" Source="extra.png"/>
                                </StackLayout>
    
                            </Grid>
    
                        </yummy:PancakeView>
    
                        <StackLayout BackgroundColor="#d4d4d4" Grid.Row="1" Orientation="Vertical">
    
                            <ListView IsVisible="{Binding hasLifeData}" ItemTapped="RSMListView_ItemTapped" 
                                  SeparatorVisibility="None" 
                                  IsPullToRefreshEnabled="False"
                                  ItemsSource="{Binding rsmLifeRankingList}" 
                                  x:Name="RSMListView" 
                                  Margin="0,0,0,2"
                                  HasUnevenRows="True">
                                <ListView.ItemTemplate>
                                    <DataTemplate>
                                        <ViewCell>
    
                                            <Frame Margin="2,4,2,4" BackgroundColor="White" IsVisible="True" HasShadow="{OnPlatform Android='true',iOS='false'}" CornerRadius="10" Padding="2,4,2,4">
    
                                                <StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" BackgroundColor="White" Orientation="Vertical">
    
                                                </StackLayout>
    
                                            </Frame>
    
                                        </ViewCell>
                                    </DataTemplate>
                                </ListView.ItemTemplate>
                            </ListView>
    
                            <StackLayout IsVisible="{Binding noData}" HorizontalOptions="CenterAndExpand" VerticalOptions="StartAndExpand">
    
                                <Image Source="nodata" HorizontalOptions="Center"/>
    
                            </StackLayout>
    
                        </StackLayout>
    
                    </Grid>
    
                </StackLayout>
    
                <yummy:PancakeView CornerRadius="10,10,0,0" Padding="0" BackgroundColor="#faf9f8"
                         x:Name="bottomSheet" RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent,
                            Property=Height,Factor=.96,Constant=0}" RelativeLayout.WidthConstraint="{ConstraintExpression
                            Type=RelativeToParent,Property=Width,Factor=1,Constant=0}" RelativeLayout.HeightConstraint="{ConstraintExpression
                            Type=RelativeToParent,Property=Height,Factor=1,Constant=0}">
                    <yummy:PancakeView.GestureRecognizers>
                        <PanGestureRecognizer PanUpdated="OnPanUpdated" />
                    </yummy:PancakeView.GestureRecognizers>
                    <StackLayout BackgroundColor="Gray" Spacing="0">
    
                        <BoxView HeightRequest="5" CornerRadius="2" Margin="0,6,0,8" WidthRequest="80" BackgroundColor="LightGray" HorizontalOptions="Center"/>
    
                        <StackLayout Orientation="Vertical">
    
                            <StackLayout IsVisible="{Binding hasLifeData}" BackgroundColor="WhiteSmoke" Orientation="Vertical" Grid.Row="1">
    
                                <StackLayout IsVisible="{Binding layoutVisible}" Spacing="0" Orientation="Vertical">
    
                                    <yummy:PancakeView Padding="10,0,10,10" CornerRadius="0,0,15,15" BackgroundColor="{StaticResource colorLife}">
    
                                        <StackLayout Orientation="Vertical">
    
    
                                        </StackLayout>
    
                                    </yummy:PancakeView>
    
                                    <ScrollView Padding="0,5,0,5">
    
                                        <StackLayout Margin="2,0,2,0" Orientation="Vertical">
    
    
    
                                        </StackLayout>
    
                                    </ScrollView>
    
                                </StackLayout>
    
                            </StackLayout>
    
                        </StackLayout>
    
                    </StackLayout>
                </yummy:PancakeView>
    
            </RelativeLayout>
    
        </ContentPage.Content>
    </ContentPage>

代码隐藏

    public partial class RSMview : ContentPage
    {
        private RSMViewModel vm;
        private string company;
        private string lifColor = "#f2b22c";
        private double x, y;
    
        public RSMview()
        {
            InitializeComponent();
        }
    
        public RSMview(string company, string userRegion)
        {
            InitializeComponent();
    
            this.company = company;
    
            BindingContext = new RSMViewModel();
            vm = BindingContext as RSMViewModel;
    
            Title = userRegion + " (RSM)";
    
            ToolbarStatusBarTheme.ToolbarWithStatusBar(company);
    
            if (NetworkCheck.IsInternet())
            {
                if (company.Equals("G"))
                {
    
                    dropdownLayout.BackgroundColor = Color.FromHex(genColor);
                    vm.GetGenRSMData(userRegion, "G");
    
                }
                else if (company.Equals("L"))
                {
    
                    dropdownLayout.BackgroundColor = Color.FromHex(lifColor);
                    vm.GetLifeRSMData(userRegion, "L");
    
                }
    
            }
    
        }
    
        private async void RSMListView_ItemTapped(object sender, ItemTappedEventArgs e)
        {
            var item = (LifeRSMData)e.Item;
            await Navigation.PushAsync(new SMviewHead(company, item));
        }
    
        protected override void OnAppearing()
        {
            base.OnAppearing();
            if (Device.Idiom == TargetIdiom.Phone)
            {
    
                CrossDeviceOrientation.Current.LockOrientation(Plugin.DeviceOrientation.Abstractions.DeviceOrientations.Portrait);
    
            }
    
        }
    
        void OnPanUpdated(object sender, PanUpdatedEventArgs e)
        {
            // Handle the pan
            switch (e.StatusType)
            {
                case GestureStatus.Running:
                    // Translate and ensure we don't y + e.TotalY pan beyond the wrapped user interface element bounds.
                    var translateY = Math.Max(Math.Min(0, y + e.TotalY), -Math.Abs((Height * .25) - Height));
                    bottomSheet.TranslateTo(bottomSheet.X, translateY, 20);
                    break;
                case GestureStatus.Completed:
                    // Store the translation applied during the pan
                    y = bottomSheet.TranslationY;
    
                    //at the end of the event - snap to the closest location
                    var finalTranslation = Math.Max(Math.Min(0, -1000), -Math.Abs(GetClosestLockState(e.TotalY + y)));
    
                    //depending on Swipe Up or Down - change the snapping animation
                    if (isSwipeUp(e))
                    {
                        bottomSheet.TranslateTo(bottomSheet.X, finalTranslation, 250, Easing.SpringIn);
                    }
                    else
                    {
                        bottomSheet.TranslateTo(bottomSheet.X, finalTranslation, 250, Easing.SpringOut);
                    }
    
                    //dismiss the keyboard after a transition
                    //SearchBox.Unfocus();
                    y = bottomSheet.TranslationY;
                   
                    break;
    
            }
    
        }
    
        public bool isSwipeUp(PanUpdatedEventArgs e)
        {
            if (e.TotalY < 0)
            {
                return true;
            }
            return false;
        }
    
        //TO-DO: Make this cleaner
        private double GetClosestLockState(double TranslationY)
        {
            //Play with these values to adjust the locking motions - this will change depending on the amount of content ona  apge
            var lockStates = new double[] { 0, .5, .88 };
    
            //get the current proportion of the sheet in relation to the screen
            var distance = Math.Abs(TranslationY);
            var currentProportion = distance / Height;
    
            //calculate which lockstate it's the closest to
            var smallestDistance = 10000.0;
            var closestIndex = 0;
            for (var i = 0; i < lockStates.Length; i++)
            {
                var state = lockStates[i];
                var absoluteDistance = Math.Abs(state - currentProportion);
                if (absoluteDistance < smallestDistance)
                {
                    smallestDistance = absoluteDistance;
                    closestIndex = i;
                }
            }
    
            var selectedLockState = lockStates[closestIndex];
            var TranslateToLockState = GetProportionCoordinate(selectedLockState);
    
            return TranslateToLockState;
        }
    
        private double GetProportionCoordinate(double proportion)
        {
            return proportion * Height;
        }
    
        private void DismissBottomSheet()
        {
    
            //SearchBox.Unfocus();
            var finalTranslation = Math.Max(Math.Min(0, -1000), -Math.Abs(GetProportionCoordinate(0)));
            bottomSheet.TranslateTo(bottomSheet.X, finalTranslation, 450, Easing.SpringOut);
            //SearchBox.Text = string.Empty;
        }
    
        private void Picker_Focused(object sender, FocusEventArgs e)
        {
            DismissBottomSheet();
        }
    
        private void OpenBottomSheet()
        {
            var finalTranslation = Math.Max(Math.Min(0, -1000), -Math.Abs(GetProportionCoordinate(.85)));
            bottomSheet.TranslateTo(bottomSheet.X, finalTranslation, 150, Easing.SpringIn);
        }
    
    }

视图模型

public class RSMViewModel : BaseViewModelHelper
   {       

       public RSMViewModel()
       {
           btnImage = "upbtn.png";
           extraBtnVisible = false;
           isKpiEnable = false;
       }

       private void CreateToplayout(string company, string sList)
       {

           if (company.Equals("L"))
           {

               if (sList != null)
               {

                   var itemList = JsonConvert.DeserializeObject<List<SummaryLifeRegionalData>>(sList);
                   //var itemList = mList.rsmLifeData;

                   if (itemList.Count > 0)
                   {

                       foreach (var item in itemList)
                       {

                           FYR_NOP_TO_BE_PAID = item.FYR_NOP_TO_BE_PAID.ToString();
                           ....

                       }

                   }
                   else
                   {

                   }

               }
               else
               {

               }

           }
           else if (company.Equals("G"))
           {

               if (sList != null)
               {
                  
                   var mList = JsonConvert.DeserializeObject<SummaryRegionalHeaderData>(sList);
                   var itemList = mList.rsmMotorData;

                   if (itemList.Count > 0)
                   {

                       foreach (var item in itemList)
                       {

                           RENEWAL_VEHICLE_COUNT = item.RENEWAL_VEHICLE_COUNT.ToString();
                           ....

                       }

                   }
                   else
                   {

                   }

               }
               else
               {

               }

           }

       }

       public void GetLifeRSMData(string p_region, string cType)
       {
           extraBtnVisible = false;
           this.p_region = p_region;
           this.companyType = cType;
           IsEnabled = false;
           SelectedItem = getCurrentMonth(cType);
       }   

       public MonthData SelectedItem
       {
           get => _selectedItem;
           set
           {
               _selectedItem = value;

               Task.Run(async () =>
               {

                   AcrDialogClass.ShowLoadingDialog("Loading...");

                   if (firstRun)
                   {

                       string selectedSelectedItem = _selectedItem.ToString();
                       string getSubStringMonth = selectedSelectedItem.Substring(1, 2);
                       string getSubStringYear = selectedSelectedItem.Substring(9, 4);

                       await ChangeListAsync(getSubStringYear, getSubStringMonth, p_region, companyType);

                       string sList = null;

                       if (companyType.Equals("L"))
                       {

                           mainBgColor = "#f2b22c";
                           sList = await _apiServices.GetLifeSummaryDataRM(getSubStringYear, getSubStringMonth, p_region);

                       }
                       else if (companyType.Equals("G"))
                       {

                           mainBgColor = "#F44336";
                           sList = await _apiServices.getRSMsummaryData(getSubStringYear, getSubStringMonth, p_region, null);

                       }

                       CreateToplayout(companyType, sList);

                   }
                   else
                   {

                       firstRun = true;

                   }

                   AcrDialogClass.HideLoadingDialog();

               });

               OnPropertyChanged();
           }


       }

       private async Task ChangeListAsync(string getSubStringYear, string getSubStringMonth, string p_region, string companyType)
       {

           if (companyType.Equals("L"))
           {
               kpiImage = "kpi_chart.png";
               isKpiEnable = false;
               IsEnabled = false;

               //lifeValue = await _apiServices.getLifeRSMDataList(getSubStringYear, getSubStringMonth, p_region, authenticateData1);
               lifeValue = await _apiServices.GetLifeRSMDataList(getSubStringYear, getSubStringMonth, p_region);

               if (lifeValue != null)
               {
                   hasLifeData = true;
                   hasGenData = false;
                   noData = false;
                   IsEnabled = true;
                   layoutVisible = true;
                   layoutVisibleGen = false;

                   foreach (LifeRSMData ss in lifeValue)
                   {
                       ss.TOTAL_PREM_TO_BE_PAID_STRING = ss.TOTAL_PREM_TO_BE_PAID.ToString("N", CultureInfo.InvariantCulture);
                       ss.LIFE_TARGET_S = ss.LIFE_TARGET.ToString("N", CultureInfo.InvariantCulture);
                       ss.LIFE_ACHIVEMENT_S = ss.LIFE_ACHIVEMENT.ToString("N", CultureInfo.InvariantCulture);
                       Device.BeginInvokeOnMainThread(() =>
                       {
                           createChart(ss);
                       });
                       
                   }

                   rsmLifeRankingList = lifeValue;

               }
               else
               {

                   hasLifeData = false;
                   hasGenData = false;
                   noData = true;
                   IsEnabled = false;
                   layoutVisible = false;
                   layoutVisibleGen = false;
                   rsmLifeRankingList.Clear();

               }

           }
           else if (companyType.Equals("G"))
           {
               kpiImage = "kpi_chart.png";
               isKpiEnable = false;
               IsEnabled = false;

               genValue = await _apiServices.getGenRSMDataList(getSubStringYear, getSubStringMonth, p_region, null);

               if (genValue != null)
               {
                   hasGenData = true;
                   hasLifeData = false;
                   noData = false;
                   IsEnabled = true;
                   layoutVisible = false;
                   layoutVisibleGen = true;

                   foreach (GenRSMData ss in genValue)
                   {
                       ss.RENEWAL_PREMIUM_TO_BE_PAID_S = ss.RENEWAL_PREMIUM_TO_BE_PAID.ToString("N", CultureInfo.InvariantCulture);
                       ss.GENERAL_TARGET_S = ss.GENERAL_TARGET.ToString("N", CultureInfo.InvariantCulture);
                       ss.GENERAL_ACHIVEMENT_S = ss.GENERAL_ACHIVEMENT.ToString("N", CultureInfo.InvariantCulture);
                       createChartGen(ss);
                   }

                   rsmGenRankingList = genValue;

               }
               else
               {

                   hasGenData = false;
                   hasLifeData = false;
                   noData = true;
                   IsEnabled = false;
                   layoutVisible = false;
                   layoutVisibleGen = false;
                   rsmGenRankingList.Clear();

               }

           }
           else
           {

           }

       }

       private void createChart(LifeRSMData ss)
       {

           var labels = new List<string>();
           var lineEntries = new List<EntryChart>();

           float achPercentg = (float)((ss.LIFE_ACHIVEMENT / ss.LIFE_TARGET) * 100);

           lineEntries.Add(new EntryChart(0, 100));
           lineEntries.Add(new EntryChart(1, achPercentg));

           labels.Add("Tar:");
           labels.Add("Ach:");

           var lineDataSet4 = new BarDataSet(lineEntries, "")
           {
               Colors = new List<Color>{
                   Color.FromHex("#248acf"), Color.FromHex("#36DBBB")
               }
           };
           var lineData4 = new BarChartData(new List<IBarDataSet>() { lineDataSet4 });

           AxisLeft = new YAxisConfig();
           AxisLeft.DrawGridLines = false;
           AxisLeft.DrawAxisLine = true;
           AxisLeft.Enabled = true;
           AxisLeft.AxisMinimum = 0;
           AxisLeft.AxisMaximum = 100;

           AxisRight = new YAxisConfig();
           AxisRight.DrawAxisLine = false;
           AxisRight.DrawGridLines = false;
           AxisRight.Enabled = false;

           XAxis = new XAxisConfig();
           XAxis.Granularity = 1f;
           XAxis.XAXISPosition = XAXISPosition.BOTTOM;
           XAxis.DrawGridLines = false;
           XAxis.DrawLabels = true;
           XAxis.AxisValueFormatter = new TextByIndexXAxisFormatter(labels);

           Legend = new LegendXF();
           Legend.Enabled = false;

           DescriptionChart = new ChartDescription();
           DescriptionChart.Enabled = false;
           DescriptionChart.Text = "";

           ss.AxisLeft = AxisLeft;
           ss.AxisRight = AxisRight;
           ss.XAxis = XAxis;
           ss.Legend = Legend;
           ss.DescriptionChart = DescriptionChart;
           ss.chartData = lineData4;
       }

       public ICommand filterCommand
       {
           get
           {
               return new Command(() =>
               {
                   if (IsEnabled)
                   {
                       if (companyType != null)
                       {
                           if (companyType.Equals("L"))
                           {
                               UserDialogs.Instance.ActionSheet(new ActionSheetConfig().SetTitle("Sort using...")
                                   .Add("Due", () => this.SortData("DueA", companyType), "fup.png")
                                   .Add("Due", () => this.SortData("DueD", companyType), "fdown.png")
                                   .Add("Achievement", () => this.SortData("AchA", companyType), "fup.png")
                                   .Add("Achievement", () => this.SortData("AchD", companyType), "fdown.png").SetUseBottomSheet(true));

                           }
                           else if (companyType.Equals("G"))
                           {
                               UserDialogs.Instance.ActionSheet(new ActionSheetConfig().SetTitle("Sort using...")
                                   .Add("Due", () => this.SortData("DueA", companyType), "fup.png")
                                   .Add("Due", () => this.SortData("DueD", companyType), "fdown.png").SetUseBottomSheet(true));
                           }
                       }
                   }
               });
           }
       }

       public ICommand regionClassCommand
       {
           get
           {
               return new Command(() =>
               {

                   Application.Current.MainPage.Navigation.PushAsync(new RSMclassView(p_region, SelectedItem));

               });
           }
       }

       private void SortData(string caseSwitch, string companyType)
       {
         
       }

       private MonthData getCurrentMonth(string cType)
       {

           DateTime now = DateTime.Now;
         
           string currMonth_2 = now.AddMonths(-2).ToString("(MM)/MMM yyyy");
           string currMonth_1 = now.AddMonths(-1).ToString("(MM)/MMM yyyy");
           string currMonth0 = now.ToString("(MM)/MMM yyyy");
           string currMonth1 = now.AddMonths(1).ToString("(MM)/MMM yyyy");

           if (cType.Equals("L"))
           {
               MyList.Add(new MonthData { mName = currMonth_2 });
               MyList.Add(new MonthData { mName = currMonth_1 });
               MyList.Add(new MonthData { mName = currMonth0 });
               MyList.Add(new MonthData { mName = currMonth1 });
           }
           else
           {
               MyList.Add(new MonthData { mName = currMonth_2 });
               MyList.Add(new MonthData { mName = currMonth_1 });
               MyList.Add(new MonthData { mName = currMonth0 });
           }

           return new MonthData { mName = currMonth0 };
       }

   }

您可以将 ListView 设置为显示在底部框架上方。 请删除 ItemListView 的外部元素并为 ItemListView 添加以下属性:

             RelativeLayout.XConstraint="{ConstraintExpression Type=Constant, Constant=0}" 
             RelativeLayout.YConstraint="{ConstraintExpression Type=Constant, Constant=0}"  
             RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1.0}"
             RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=1.0}"

整个代码是:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             BackgroundColor="Yellow"
             x:Class="TestBottomSheet.MainPage">

    <RelativeLayout>

            <ListView x:Name="ItemListView" HasUnevenRows="true" 
                 RelativeLayout.XConstraint="{ConstraintExpression Type=Constant, Constant=0}" 
                 RelativeLayout.YConstraint="{ConstraintExpression Type=Constant, Constant=0}"  
                 RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1.0}"
                 RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.91}"    
                      
                      >
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <Frame HasShadow="True" BackgroundColor="White" CornerRadius="15" Margin="5">
                                <StackLayout Orientation="Vertical">
                                    <Label Text="{Binding title}" FontSize="Medium"/>
                                    <Label Text="{Binding id}" FontSize="Default"/>
                                </StackLayout>
                            </Frame>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
    
       
        <Frame HasShadow="true" CornerRadius="8" Padding="1,4,1,0" BackgroundColor="#faf9f8"
                     x:Name="bottomSheet" RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent,
                        Property=Height,Factor=.92,Constant=0}" RelativeLayout.WidthConstraint="{ConstraintExpression
                        Type=RelativeToParent,Property=Width,Factor=1,Constant=0}" RelativeLayout.HeightConstraint="{ConstraintExpression
                        Type=RelativeToParent,Property=Height,Factor=1,Constant=0}">
            <Frame.GestureRecognizers>
                <PanGestureRecognizer PanUpdated="OnPanUpdated" />
            </Frame.GestureRecognizers>
            <StackLayout Spacing="5">
                <BoxView HeightRequest="5" CornerRadius="2" WidthRequest="50" BackgroundColor="Gray" HorizontalOptions="Center"/>
                <StackLayout BackgroundColor="White" HeightRequest="25">
                    
                </StackLayout>

                <ListView x:Name="ItemListView2" HasUnevenRows="true" >
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <ViewCell>
                                <Frame HasShadow="True" BackgroundColor="FloralWhite" CornerRadius="15" Margin="5">
                                    <StackLayout Orientation="Vertical">
                                        <Label Text="{Binding id}" FontSize="Default"/>
                                    </StackLayout>
                                </Frame>
                            </ViewCell>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>

            </StackLayout>
        </Frame>
    </RelativeLayout>

</ContentPage>

结果是: