Search code examples
cxamlmaui

Access to nested XAML elements


** Good afternoon!** Situation, there is another collectionView inside the collectionView. From the code I get to the methods and properties of the first collectionView by means of an attribute

x:Name="cv1"

But there is no access to the second collection from the code. The error is this The name "cv2" does not exist in the current context. My XAML:

<CollectionView x:Name="cv1">
   <CollectionView.ItemTemplate>
      <DataTemplate>
         <Frame Margin="5">
            <Frame.GestureRecognizers>
               <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/>
            </Frame.GestureRecognizers>
            <StackLayout>
               <Label Text="{Binding Key}"/>
               <CollectionView x:Name="cv2">
                  <CollectionView.ItemTemplate>
                     <DataTemplate>
                        <StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand">
                           <Label Text="{Binding DateCase}" HorizontalOptions="Start"/>
                           <Label Text="{Binding NumCase}" HorizontalOptions="CenterAndExpand"/>
                           <Label Text="{Binding Serial}" HorizontalOptions="CenterAndExpand"/>
                           <Label Text="{Binding Time}" HorizontalOptions="End"/>
                        </StackLayout>
                     </DataTemplate>
                  </CollectionView.ItemTemplate>
               </CollectionView>
            </StackLayout>
         </Frame>
      </DataTemplate>
   </CollectionView.ItemTemplate>
</CollectionView>

Here is from the code:

cv1.ItemsSource = Cases; //There is access to the collection
cv2.ItemsSource = TimeLine; //There is no access to the collection
cv2.IsVisible = flag;

Tell me what's wrong? Which way to dig? Thanks.

Expected: By clicking on the Frame that contains the Collectionview, the isVisible property changed its value.

Turn out: That there is no access to the collectionView inside the Frame, which, in turn, is not inside the collectionView.


Solution

  • Of course you cant access cv2 from code. The name CV2 is part of the data template, not your page.

    What you actually ask is: How to access control in DataTemplate.

    There is new CV2 generated, each time you insert CV1 item. You need to search for it, in the context of the current item. (If you need to use this approach)

    What you actually have to do is:

    1. Use binding.
    2. Set x:DataType for your DataTemplate (CV1 item).
    3. Bind your CV2 ItemSource to a List to the set x:DataType Model.

    (Edit) Example how to do it:

    Lets say you have Model, you want to use for every item in your CollectionView. To bind it you need to specify

    <DataTemplate x:DataType="model:MyModel">
    

    This "model:" is a namespace. You set it in your content page.

    xmlns:model="clr-namespace:MyNameSpace"
    

    After that if you have lets say Image in your DataTemplate, you can do this:

    <Image Source="{Binding Image}"\>
    

    Where Image is property of your MyModel class. The VisualElement (In this case Image) will be getting its properties, from the property of your model.

    All you have to do is to bind your ObservableCollection of type MyModel to the ItemSource of your CollectionView.

    <CollectionView ItemsSource="{Binding MyModels}">
    

    In your ViewModel you have:

     [ObservableProperty]
     ObservableCollection<MyModel> _myModels= new();
    

    Off-topic: What you will need eventually is RangeObservableCollection. Where you will be able to silently add list of items, and notify that you finished added items, so you don't trigger OnChange for every item. Performance of your CollectionView will suffer, when you add too many items otherwise.

    I like to manually write the class and inherit ObservableCollection, but there are such classes in other libraries that you can use.