This content has 5 years. Some of the information in this post may be out of date or no longer work. Please, read this page keeping its age in your mind.

Formsban, ha egy ListView HorizontalOptions, VerticalOptions tulajdonságait Fill-re állítjuk, és a ListView egy Grid sorában van mondjuk, amelynek a Height-je Auto, a lista le fogja foglalni a Grid által kínált összes helyet. Ez azért van, mert a ListView measure-nél még nem tudja hogy milyen listaelemek milyen listaelem formátummal fognak megjelenni benne. Így elveszítjük a lehetőséget a dinamikus megjelenítésre, mert a felületünk szét fog csúszni.

Ennek a problémakörnek megoldásaképpen készítettem egy olyan ListView-t, amely képes a listaelemek tényleges lemért magassága után újraméretezni a lista magasságát. Ez a lista, mindig a benne található elemek magassága méretűre fog nyúlni. Meg lehet még fűszerezni annyival, hogy a Separatorok magasságát is beleszámolja, illetve hogy legyen egy maximálisan engedett magassága is, én ezt nem tettem meg, de jó kiindulási alap.

 public class AutoHeightListView : ListView
    {
        public AutoHeightListView()
        {
        }

        protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            base.OnPropertyChanged(propertyName);

            // ItemsSource változásakor 
            if (propertyName == nameof(ListView.ItemsSource))
            {
                if(ItemsSource != null)
                {
                    // Kikérjük a ListView feltemapltezett celljeit.
                    IEnumerable<PropertyInfo> pInfos = (this as ItemsView<Cell>).GetType().GetRuntimeProperties();
                    var templatedItems = pInfos.FirstOrDefault(info => info.Name == "TemplatedItems");

                    if (templatedItems != null)
                    {
                        var cells = templatedItems.GetValue(this);
                        if(cells is Xamarin.Forms.ITemplatedItemsList<Xamarin.Forms.Cell> cellsCasted)
                        {
                            if(cellsCasted.Count != 0)
                            {
                                ((ViewCell)cellsCasted.Last()).View.SizeChanged += FirstElementHeightChanged;
                            }
                        }
                    }
                }
            }
        }

        double prevHeight = 0;

        private void FirstElementHeightChanged(object sender, EventArgs e)
        {
            SetHeightRequestByCellsHeight();
        }

        /// <summary>
        /// Megméri minden sor Viewcell magasságát, és az egész listview magasságát ezeknek az összegére állítja be.
        /// </summary>
        private void SetHeightRequestByCellsHeight()
        {
            double calculatedHeight = 0;

            // Kikérjük a ListView feltemapltezett celljeit.
            IEnumerable<PropertyInfo> pInfos = (this as ItemsView<Cell>).GetType().GetRuntimeProperties();
            var templatedItems = pInfos.FirstOrDefault(info => info.Name == "TemplatedItems");

            if (templatedItems != null)
            {
                var cells = templatedItems.GetValue(this);
                foreach (ViewCell cell in cells as Xamarin.Forms.ITemplatedItemsList<Xamarin.Forms.Cell>)
                {
                    calculatedHeight += cell.View.Height;
                }
            }

            if (calculatedHeight == prevHeight)
                return;

            prevHeight = calculatedHeight;
            HeightRequest = calculatedHeight;
        }
    }