How to use Xamarin DataTemplateSelector with DataTemplates organized in folders?

861 views Asked by At

I'm trying to implement something like this MS Docs sample, with the DataTemplates as separate files: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/templates/data-templates/selector

My folder structure...

Project
 |
 └─ Views\
     |  MyView.xaml
     |
     └───DataTemplates\
           DT1.xaml (no .cs)
           DT2.xaml (no .cs)
           DTSelector.cs

From MyView.xaml...

<ContentPage ...             
    xmlns:datatemplates="clr-namespace: Project.Views.DataTemplates"/>
<ContentPage.Resources>
    <ResourceDictionary>

        <ResourceDictionary.MergedDictionaries>       
            <datatemplates:DT1/> 
            <datatemplates:DT2/>
            <!-- This is the x:Key name, right? -->
            <!-- Intellisense can't find these  -->
        </ResourceDictionary.MergedDictionaries>

        <datatemplates:DTSelector x:Key="dTSelector"        
            DT1= "{StaticResource dT1}"
            DT2= "{StaticResource dT2}"/> 

    </ResourceDictionary>

From a DataTemplate...

<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">    
    <!-- x:Class has been removed -->
    <DataTemplate x:Name="DT1" x:Key="dT1">
        <Grid, etc...

DataTemplateSelector...

public class DTSelector: DataTemplateSelector
{    
    public DataTemplate DT1{ get; set; }
    public DataTemplate DT2{ get; set; }

    protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
    {    
        switch (App.CurrentUser.SomeEnum)
        {
            case SomeEnum.Pref1:
                 return DT1;
                 break;
            case SomeEnum.Pref2:
                return DT2;
                break;
            default:
                return DT1;
        }
    }
}

I have wrestled the code into the App level and got it to compile, but then DTSelector's always returns a null object, and it throws an exception. I'd prefer it at the page level, anyhow. It seems like there should be a... ResourceDictionary Source="DT1.xaml" x:Key="DT1" but that's not valid.

I assume MyView can't find the templates via xmlns because Intellisense only sees cs files... but I get a green squiggle and compilation error XLS0414: "The type 'datatemplates:DT1' not found..."

GitRepo here, for your pleasure: https://github.com/BullCityCabinets/DataTemplateSelectorExample201014

Thanks for any help!

1

There are 1 answers

3
nevermore On

I found if you put the DT1.xaml and MyView.xaml in the same folder. You can reference the resource dictionary by :

<ContentPage.Resources>

    <ResourceDictionary Source="DT1.xaml" />
    <ResourceDictionary Source="DT2.xaml" />

    <datatemplates:DTSelector x:Key="dTSelector"        
            DT1ref = "{StaticResource DT1key}"
            DT2ref = "{StaticResource DT2key}"/>

</ContentPage.Resources>

And the folder:

enter image description here

Refer: merge-local-resource-dictionaries