public DataTemplate GetTemplate(IVirtualListViewAdapter adapter, int position)
        {
            if (position == 0)
            {
                if (HeaderTemplate != null)
                {
                    return(HeaderTemplate);
                }

                if (SectionHeaderTemplateSelector != null)
                {
                    return(SectionHeaderTemplateSelector.SelectGroupTemplate(adapter, 0));
                }

                if (SectionHeaderTemplate != null)
                {
                    return(SectionHeaderTemplate);
                }
            }

            var linear = 0;

            if (HeaderTemplate != null)
            {
                linear++;
            }

            for (int s = 0; s < adapter.Sections; s++)
            {
                if (HasSectionHeader)
                {
                    if (position == linear)
                    {
                        return(SectionHeaderTemplateSelector?.SelectGroupTemplate(adapter, s)
                               ?? SectionHeaderTemplate);
                    }
                    linear++;
                }

                var itemsInSection = adapter.ItemsForSection(s);

                // It's an item in the section, return it for this item
                if (position < linear + itemsInSection)
                {
                    var itemIndex = position - linear;
                    return(ItemTemplateSelector?.SelectItemTemplate(adapter, s, itemIndex) ?? ItemTemplate);
                }

                linear += itemsInSection;

                if (HasSectionFooter)
                {
                    if (position == linear)
                    {
                        return(SectionFooterTemplateSelector?.SelectGroupTemplate(adapter, s)
                               ?? SectionFooterTemplate);
                    }
                    linear++;
                }
            }

            return(FooterTemplate);
        }
        public (DataTemplate template, PositionInfo info) GetTemplateAndInfo(IVirtualListViewAdapter adapter, int sectionIndex, int itemIndex)
        {
            var realSectionIndex = sectionIndex;

            if (HasGlobalHeader)
            {
                if (sectionIndex == 0)
                {
                    return(HeaderTemplate, new PositionInfo
                    {
                        Kind = PositionKind.Header
                    });
                }

                // Global header takes up a section, real adapter is 1 less
                realSectionIndex--;
            }

            var realNumberOfSections = adapter.Sections;

            if (HasGlobalFooter)
            {
                if (realSectionIndex >= realNumberOfSections)
                {
                    return(FooterTemplate, new PositionInfo
                    {
                        Kind = PositionKind.Footer
                    });
                }
            }


            var realItemsInSection = adapter.ItemsForSection(realSectionIndex);

            var realItemIndex = itemIndex;

            var itemsAdded = 0;

            if (HasSectionHeader)
            {
                itemsAdded++;
                realItemIndex--;

                if (itemIndex == 0)
                {
                    return(SectionHeaderTemplateSelector?.SelectGroupTemplate(adapter, realSectionIndex) ?? SectionHeaderTemplate,
                           new PositionInfo
                    {
                        Kind = PositionKind.SectionHeader,
                        ItemsInSection = realItemsInSection,
                        SectionIndex = realSectionIndex,
                        BindingContext = adapter.Section(realSectionIndex),
                        NumberOfSections = realNumberOfSections
                    });
                }
            }

            if (HasSectionFooter)
            {
                itemsAdded++;

                if (itemIndex >= realItemsInSection + itemsAdded - 1)
                {
                    return(SectionFooterTemplateSelector?.SelectGroupTemplate(adapter, realSectionIndex) ?? SectionFooterTemplate,
                           new PositionInfo
                    {
                        Kind = PositionKind.SectionFooter,
                        ItemsInSection = realItemsInSection,
                        SectionIndex = realSectionIndex,
                        BindingContext = adapter.Section(realSectionIndex),
                        NumberOfSections = realNumberOfSections
                    });
                }
            }

            return(ItemTemplateSelector?.SelectItemTemplate(adapter, realSectionIndex, realItemIndex) ?? ItemTemplate,
                   new PositionInfo
            {
                Kind = PositionKind.Item,
                ItemsInSection = realItemsInSection,
                SectionIndex = realSectionIndex,
                ItemIndex = realItemIndex,
                BindingContext = adapter.Item(realSectionIndex, realItemIndex),
                NumberOfSections = realNumberOfSections,
            });
        }