Xamarin.Forms DataTemplateSelector not working for HeaderTemplate in CollectionView

726 Views Asked by At

I have declared some Datatemplates for my Collectionviews Header to use as an Template.

    <ResourceDictionary>
      <!--#region HeaderTemplates-->
      <DataTemplate x:Key="translationHeaderTemplate">
        <Frame x:Name="translationDropTarget" Margin="5">
          <Label Style="{x:StaticResource boldLabelStyle}" Text="{Binding SolutionDisplay}" FontSize="Medium" HorizontalOptions="Center" HeightRequest="50" VerticalOptions="Center" x:Name="FrameLabel"></Label>
          <Frame.GestureRecognizers>
            <DropGestureRecognizer AllowDrop="True" DropCommand="{Binding DropOverCommand}">
            </DropGestureRecognizer>
          </Frame.GestureRecognizers>
        </Frame>
      </DataTemplate>
      <DataTemplate x:Key="pictureHeaderTemplate">
        <Frame x:Name="pictureDropTarget" Margin="5">
          <Image Source="{Binding SolutionIconString}" HorizontalOptions="FillAndExpand" MinimumWidthRequest="50" HeightRequest="100" VerticalOptions="CenterAndExpand" x:Name="FrameImage"></Image>
          <Frame.GestureRecognizers>
            <DropGestureRecognizer AllowDrop="True" DropCommand="{Binding DropOverCommand}">
            </DropGestureRecognizer>
          </Frame.GestureRecognizers>
        </Frame>
      </DataTemplate>
      <DataTemplate x:Key="ttsHeaderTemplate">
        <Frame x:Name="ttsDropTarget" Margin="5">
          <forms:AnimationView x:Name="XAnim" AutoPlay="true" VerticalOptions="CenterAndExpand" RepeatMode="Infinite" HorizontalOptions="CenterAndExpand" Animation="soundIcon.json"
                               Clicked="XAnim_Clicked" ></forms:AnimationView>
          <Frame.GestureRecognizers>
            <DropGestureRecognizer AllowDrop="True" DropCommand="{Binding DropOverCommand}">
            </DropGestureRecognizer>
          </Frame.GestureRecognizers>
        </Frame>
      </DataTemplate>
      <!--#endregion-->
      <DataTemplate x:Key="translationTemplate">
        <Frame HasShadow="True" CornerRadius="15" VerticalOptions="Start" HeightRequest="70">
          <StackLayout>
            <Label
                  Text="{Binding DisplayString}"
                  Style="{x:StaticResource mediumlabelStyle}"
                  VerticalOptions="CenterAndExpand"
                    HorizontalOptions="Center"
                  FontSize="Small">
            </Label>
          </StackLayout>
          <Frame.GestureRecognizers>
            <DragGestureRecognizer
                    DragStartingCommand="{Binding Path=BindingContext.DragStartingCommand, Source={x:Reference ViewCollection}}"
                    DragStartingCommandParameter="{Binding .}"/>
          </Frame.GestureRecognizers>
        </Frame>
      </DataTemplate>
      <vokabelmodul:VocabularyViewTemplateSelector
        x:Key="vocViewTemplateSelector"
        TranslationTemplate="{StaticResource translationHeaderTemplate}"
        PictureTemplate="{StaticResource pictureHeaderTemplate}"
        TTSTemplate="{StaticResource ttsHeaderTemplate}"/>
    </ResourceDictionary>
  </ContentPage.Resources>

And I'm trying to consume it within my CollectionView with the templateselector :

      <ContentPage.Content>
    <AbsoluteLayout>
      <StackLayout
      AbsoluteLayout.LayoutBounds="0,0,1,1"
      AbsoluteLayout.LayoutFlags="All">
        <Frame>
          <StackLayout>
            <Label Style="{x:StaticResource labelStyle}" FontSize="Small" x:Name="TimerLabel" Text="{Binding Remaining}"></Label>
            <ProgressBar x:Name="Progress" Progress="{Binding Progress}" ProgressColor="Blue"></ProgressBar>
          </StackLayout>
        </Frame>
        <StackLayout x:Name="InnerStack">
          <CollectionView      
          x:Name="ViewCollection"
          ItemsSource="{Binding ViewObjects}"
          VerticalOptions="Center"
          Margin="5"
            ItemTemplate="{StaticResource translationTemplate}"
            HeaderTemplate="{StaticResource vocViewTemplateSelector}"
            Header="{Binding .}"
            >
            <CollectionView.EmptyView>
              <Label Text="No VocabularyItems!" Style="{x:StaticResource boldLabelStyle}"></Label>
            </CollectionView.EmptyView>
            <CollectionView.ItemsLayout>
              <GridItemsLayout
              Orientation="Vertical"
              HorizontalItemSpacing="5"
              VerticalItemSpacing="5"
              Span="2"/>
            </CollectionView.ItemsLayout>
          </CollectionView>
        </StackLayout>
      </StackLayout>
    </AbsoluteLayout>
  </ContentPage.Content>

But when I run the Programm I'm always getting "System.InvalidOperationException: 'LoadTemplate should not be null'".

When I'm binding my HeaderTemplate directly like this:

 HeaderTemplate="{StaticResource someHeaderTemplate}"

it works just fine.

I've added a log and breakpoint to my TemplateSelector Class but OnSelectTemplate doesn't even get called. I've also used another Templateselector for my ItemTemplate and that one worked just fine.

Any Help would be appreciated.

1

There are 1 best solutions below

6
Wen xu Li On
  1. In your xaml page, your DataTemplate tag does not add any data or styles, you need to add styles to each DataTemplate tag.

  2. You have not bound the Header data of the CollectionView. You need to add Header="{Binding ViewObjects}" to your CollectionView tag.

This is my xaml code for your reference, I hope it can solve your problem:

<ContentPage.Resources>
    <ResourceDictionary>
        <DataTemplate x:Key="someHeaderTemplate">
            <Label Text="aaa" BackgroundColor="LightPink"></Label>
        </DataTemplate>
        <DataTemplate x:Key="someOtherHeaderTemplate">
            <Label Text="bbb" BackgroundColor="Green"></Label>
        </DataTemplate>
        <DataTemplate x:Key="someThirdHeaderTemplate">
            <Label Text="ccc" BackgroundColor="Yellow"></Label>
        </DataTemplate>
        <nameSpace:templateSelector x:Key="templateSelector"
            first="{StaticResource someHeaderTemplate}"
            second="{StaticResource someOtherHeaderTemplate}"
            third="{StaticResource someThirdHeaderTemplate}"/>
    </ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
    <CollectionView
      x:Name="ViewCollection"
      Header="{Binding ViewObjects}"
      ItemsSource="{Binding ViewObjects}"
      VerticalOptions="Center"
      Margin="5"
      HeaderTemplate="{StaticResource templateSelector}">
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <Label></Label>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
</StackLayout>