1
votes

I was trying to nest a collectionView inside another, but I am having troubles when it comes to binding the ItemsSource property of the nested one, even though the method by which I have created the ObservableCollection and binded it to the ItemsSource property is the same for both collectionViews. Any idea what am I doing wrong?

XAML code:

    <ContentPage.Resources>
        <ResourceDictionary>
            <selectors:FirstSelector x:Key="First"/>
            <selectors:SecondSelector x:Key="Second"/>
        </ResourceDictionary>
    </ContentPage.Resources>

    <renderers:GradientLayout
        ColorsList="#FFFFFF,#FFFFFF"
        Mode="ToBottomLeft"
        Padding="10,50,10,0">
        
        <ScrollView>
            <StackLayout>
                <CollectionView
                    ItemsSource="{Binding FirstList}"
                    ItemTemplate="{StaticResource First}"

                    VerticalOptions="FillAndExpand"
                    HorizontalOptions="FillAndExpand"
                    Margin="0,0,0,15">

                    <CollectionView.ItemsLayout>
                        <LinearItemsLayout
                            Orientation="Vertical"
                            ItemSpacing="15"/>
                    </CollectionView.ItemsLayout>

                    <CollectionView.Resources>

                        <DataTemplate x:Key="Normal">
                            <Grid
                                HeightRequest="400"
                                HorizontalOptions="FillAndExpand"
                                ColumnDefinitions="20*,30*,25*,25*"
                                RowDefinitions="15*,70*,15*">

                                <Frame
                                    Padding="0"
                                    HasShadow="False"
                                    BackgroundColor="Pink"
                                    CornerRadius="30"
                                    IsClippedToBounds="True"

                                    Grid.Column="0"
                                    Grid.Row="1"
                                    Grid.ColumnSpan="4">
                                    <CollectionView
                                        ItemTemplate="{StaticResource Second}"
                                        ItemsSource="{Binding SecondList}"

                                        BackgroundColor="Blue"
                                        VerticalOptions="FillAndExpand"
                                        HorizontalOptions="FillAndExpand">

                                        <CollectionView.ItemsLayout>
                                            <LinearItemsLayout
                                                Orientation="Horizontal"
                                                ItemSpacing="0">
                                            </LinearItemsLayout>
                                        </CollectionView.ItemsLayout>

                                        <CollectionView.Resources>
                                            <DataTemplate x:Key="NormalTwo">
                                                <Grid
                                                    WidthRequest="392"
                                                    BackgroundColor="Orange"
                                                    ColumnDefinitions="100*"
                                                    RowDefinitions="100*"

                                                    VerticalOptions="FillAndExpand"
                                                    HorizontalOptions="FillAndExpand"
                                                    Padding="0">

                                                    <Frame
                                                        BackgroundColor="Purple"
                                                        HasShadow="False"
                                                        CornerRadius="20"

                                                        Padding="0"
                                                        Grid.Column="0"
                                                        Grid.Row="0">
                                                        <Image
                                                            Margin="-2,0,0,0"
                                                            Source="source.jpg"
                                                            Aspect="AspectFill"
                                                            HeightRequest="200">
                                                        </Image>
                                                    </Frame>
                                                </Grid>
                                            </DataTemplate>
                                        </CollectionView.Resources>
                                    </CollectionView>
                                </Frame>
                            </Grid>
                        </DataTemplate>
                    </CollectionView.Resources>
                </CollectionView>
            </StackLayout>
        </ScrollView>
    </renderers:GradientLayout>

ViewModel code:

    public class HomeViewModel : FreshBasePageModel
    {
        public static ObservableCollection<OneForAllModel> firstlist;
        public ObservableCollection<OneForAllModel> FirstList
        {
            get
            {
                return pictureList;
            }
            set
            {
                pictureList = value;
            }
        }

        public ObservableCollection<PictureModel> secondlist;
        public ObservableCollection<PictureModel> SecondList
        {
            get
            {
                return secondcollectionlist;
            }
            set
            {
                secondcollectionlist = value;
            }
        }

        public HomeViewModel(InavigationService _navigation, IDatabaseApiHelper _DataBaseApi)
        {
            Navigation = _navigation;
            DataBaseApi = _DataBaseApi;

            //Creates a provisional list necessary to show the skeleton loading UI effect
            OneForAllModel loadingPicture = new OneForAllModel()
            {
                //content
            };

            ObservableCollection<OneForAllModel> LoadingList = new ObservableCollection<OneForAllModel>()
            {
                loadingPicture,
                loadingPicture,
                loadingPicture,
                loadingPicture,
                loadingPicture,
                loadingPicture,
                loadingPicture,
                loadingPicture,
                loadingPicture,
                loadingPicture,
            };
//This list is binded to the first collection view item source and works perfectly
            FirstList = LoadingList;

            #region SecondCollectionViewBelongins
            PictureModel a = new PictureModel()
            {
                //content
            };
            PictureModel b = new PictureModel()
            {
                //content
            };

            ObservableCollection<PictureModel> list = new ObservableCollection<PictureModel>()
                {
                    a,
                    b
                };
            SecondList = list;
**//This second binding does not seem to work**
            #endregion
        }

That is all, if you need more information I will provide it as soon as I see your request, thank you all so much for your time, have a good day.

3

3 Answers

1
votes

This looks to be a BindingContext issue. You are binding the first CollectionView correctly to FirstList. This means an Item will be created for each item in that list. Each item will have a BindingContext of type OneForAllModel.

Because you are then creating another CollectionView within that item it is trying to find a property called SecondList on the OneForAllModel instead of the HomeViewModel.

Try adding a a RelativeSource binding to your SecondList binding.

It should look something like this

<CollectionView ItemTemplate="{StaticResource Second}"
                ItemsSource="{Binding Source={RelativeSource AncestorType={x:Type HomeViewModel}}, Path=SecondList}"
                BackgroundColor="Blue"
                VerticalOptions="FillAndExpand"
                HorizontalOptions="FillAndExpand">

Here's a link to the documentation on Relative Bindings for reference: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/relative-bindings

1
votes

When binding inside a binding we have to give the binding context.

First give the name for content page.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             x:Name="Root">

Then refer the binding context

ItemsSource="{Binding Source={x:Reference Root},Path=BindingContext.SecondList}"

Here is the documentation. https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/basic-bindings

0
votes

Maybe you should use StackLayout with a BindableLayout instead of the CollectionView.

Here is an example: https://stackoverflow.com/a/66591841/2472664