Search code examples
c#xamlmauicollectionview

Nested CollectionView or Displaying nested data inside of a collection view


I am trying to avoid bad practice by NOT adding a Collection View inside of a Collection view to display nested data and I have a class of

   public partial class Items
   {
        public int itemNumber { get; set; }
        public string itemdescr{ get; set; }
        public List<Items> Child { get; set; }
    }
    

my collection view looks as such

<CollectionView x:Name="CollectionViewBoM" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="9" ItemsSource="{Binding Data}">
                    <CollectionView.ItemTemplate>
                        <DataTemplate >
                            <mct:Expander >
                                <mct:Expander.Header>
                                    <Grid HeightRequest="45" MaximumHeightRequest="90" ColumnSpacing="1" RowSpacing="2">
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="240"/>
                                            <ColumnDefinition Width="*"/>
                                        </Grid.ColumnDefinitions>
                                        <BoxView Grid.Column="0" Style="{DynamicResource ContentBoxView}"/>
                                        <BoxView Grid.Column="1" Style="{DynamicResource ContentBoxView}"/>
                                        <Label TextColor="{DynamicResource SecondaryTextColor}" Grid.Column="0" Text="{Binding itemNumber}" Style="{DynamicResource ContentLabel}"/>
                                        <Label TextColor="{DynamicResource SecondaryTextColor}" Grid.Column="1" Text="{Binding Description}" Style="{DynamicResource ContentLabel}"/>
                                    </Grid>
                                </mct:Expander.Header>
                                <mct:Expander.Content x:Name="CollectionViewChild">
                                    <StackLayout BindableLayout.ItemsSource="{Binding Child}">
                                        <BindableLayout.ItemTemplate>
                                            <DataTemplate>
                                                <HorizontalStackLayout>
                                                    <Label Text="{Binding itemNumber}" />
                                                    <Label Text="{Binding itemdescr}"  Margin="10,0,0,0"/>
                                                </HorizontalStackLayout>
                                            </DataTemplate>
                                        </BindableLayout.ItemTemplate>
                                    </StackLayout>
                                </mct:Expander.Content>
                            </mct:Expander>
                        </DataTemplate>
                    </CollectionView.ItemTemplate>
                </CollectionView>

I am binding to the view model as such but I am able to see the Data but not able to see the Child data. Am I incorrectly using the BindableLayout.ItemsSource?


        [ObservableProperty]
        public List<Items> data;

Solution

  • You can recheck if you could get the inner list data(Child) correctly.

    Based on your code, I made a demo to achieve this functionality, and it could work properly.

    You can refer to the following code:

    public partial class MyViewModel:ObservableObject 
    {
        [ObservableProperty]
        public List<Items> data;
    
        public MyViewModel()
        {
            List<Items> Childs = new List<Items>();
    
            Childs.Add(new Items { itemNumber = 01 - 1, itemdescr = "desc-01-1" });
            Childs.Add(new Items { itemNumber = 02 - 1, itemdescr = "desc-02-1" });
            Childs.Add(new Items { itemNumber = 03 - 1, itemdescr = "desc-03-1" });
    
            Data = new List<Items>();
            Data.Add(new Items { itemNumber= 01, itemdescr ="desc-01",Child= Childs });
            Data.Add(new Items { itemNumber= 02, itemdescr ="desc-02", Child = Childs });
            Data.Add(new Items { itemNumber= 03, itemdescr ="desc-03", Child = Childs });
            Data.Add(new Items { itemNumber= 04, itemdescr ="desc-04" , Child = Childs });
            Data.Add(new Items { itemNumber= 05, itemdescr ="desc-05" , Child = Childs });
            Data.Add(new Items { itemNumber= 06, itemdescr ="desc-06" , Child = Childs });
            
        }
    }
    

    Usage:

    <?xml version="1.0" encoding="utf-8" ?> 
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 x:Class="MauiMVVMToolkitApp.MyPage"
                 xmlns:viewmodel="clr-namespace:MauiMVVMToolkitApp.ViewModels"
                 xmlns:mct="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
                 Title="MyPage">
    
        <ContentPage.BindingContext>
            <viewmodel:MyViewModel></viewmodel:MyViewModel>
        </ContentPage.BindingContext>
        <VerticalStackLayout>
            <CollectionView x:Name="CollectionViewBoM" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="9" ItemsSource="{Binding Data}">
                <CollectionView.ItemTemplate>
                    <DataTemplate >
                        <mct:Expander >
                            <mct:Expander.Header>
                                <Grid HeightRequest="45" MaximumHeightRequest="90" ColumnSpacing="1" RowSpacing="2">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="240"/>
                                        <ColumnDefinition Width="*"/>
                                    </Grid.ColumnDefinitions>
                                    <!--<BoxView Grid.Column="0" />
                                    <BoxView Grid.Column="1" />-->
                                    <Label  Grid.Column="0" Text="{Binding itemNumber}" />
                                    <Label  Grid.Column="1" Text="{Binding Description}" />
                                </Grid>
                            </mct:Expander.Header>
                            <mct:Expander.Content x:Name="CollectionViewChild">
                                <StackLayout BindableLayout.ItemsSource="{Binding Child}">
                                    <BindableLayout.ItemTemplate>
                                        <DataTemplate>
                                            <HorizontalStackLayout>
                                                <Label Text="{Binding itemNumber}" />
                                                <Label Text="{Binding itemdescr}"  Margin="10,0,0,0"/>
                                            </HorizontalStackLayout>
                                        </DataTemplate>
                                    </BindableLayout.ItemTemplate>
                                </StackLayout>
                            </mct:Expander.Content>
                        </mct:Expander>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>
        </VerticalStackLayout>
    </ContentPage>
    

    Note:

    For the sake of code brevity, I commented out the two BoxView of the layout.

    Besides, I noticed that the class Items should also contain another attribute Description, and that the property of the Class Items(Child), whose internal child elements are also of type Items. Please pay attention to this when initializing the data.