Reynevan
Reynevan

Reputation: 1545

How do I self-reference a DataTemplate in UWP XAML Resources?

I've seen something along these lines done with {DynamicResource xyz}on some other SO question, but it doesn't seem to work with UWP. Here's my XAML:

<DataTemplate x:Key="commentTemplate">
    <StackPanel>
        <Grid Margin="4" Background="#40606060" MinHeight="64">
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="auto" />
            </Grid.RowDefinitions>
            <StackPanel>
                <TextBlock Margin="4" FontSize="14" TextWrapping="WrapWholeWords" Text="{Binding Path=Message, Mode=OneWay}" />
                <Image MaxHeight="96" Source="{Binding Path=Image}" HorizontalAlignment="Left" Margin="4" />
            </StackPanel>
            <StackPanel Background="#18808080" Orientation="Horizontal" Grid.Row="1">
                <FontIcon Margin="2,0" Glyph="&#xE19D;" />
                <TextBlock Margin="2,0" Text="{Binding Path=Score, Mode=OneWay}" />
                <Button Content="Reply" Margin="2,0" />
            </StackPanel>
        </Grid>
        <ItemsControl ItemTemplate="{RelativeSource Mode=Self}" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Margin="48" ItemsSource="{Binding Path=Comments}" />
    </StackPanel>
</DataTemplate>

I'd like to self-reference the DataTemplate in the ItemsControl's ItemTemplate property. How would I go about replacing it?

Upvotes: 0

Views: 1345

Answers (1)

Mark W
Mark W

Reputation: 1050

Here is something that may work for you. I use this in our POS application - although this is my first attempt at nesting it. The xaml designer complains because of the selector StaticResource reference prior to its declaration, but it works at runtime.

Essentially, I use this to select a different data template based on the class that is bound to the item. In this case, there is only one type, so really we are just using the class type to decide what template to use.

MyModel:

public class MyModel
{
    public int Id { get; set; }
    public string Desc { get; set; }
    public List<MyModel> Children { get; set; }
}

MyTemplateSelector:

public class MyTemplateSelector : DataTemplateSelector
{
    public DataTemplate MyModelTemplate { get; set; }
    protected override DataTemplate SelectTemplateCore(object item)
    {
        if (item is MyModel)
        {
            return MyModelTemplate;
        }
        else
        {
            return null;
        }
    }

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        return SelectTemplateCore(item);
    }
}

My MainPage:

<Page
    x:Class="App7.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App7"
    xmlns:models="using:App7.Models"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Page.Resources>

        <DataTemplate x:Key="myModelTemplate" x:DataType="models:MyModel">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <TextBlock Text="{x:Bind Path=Desc, Mode=OneWay}" />
                <ListView Grid.Row="1" ItemTemplateSelector="{StaticResource selector}" ItemsSource="{x:Bind Path=Children, Mode=OneWay}" />
            </Grid>
        </DataTemplate>
        <local:MyTemplateSelector x:Key="selector" MyModelTemplate="{StaticResource myModelTemplate}" />
    </Page.Resources>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <ListView x:Name="lstView" ItemTemplateSelector="{StaticResource selector}" >

        </ListView>
    </Grid>
</Page>

My code behind:

public sealed partial class MainPage : Page
{
    List<MyModel> lst { get; set; }
    public MainPage()
    {
        this.InitializeComponent();
        BuildList();
        lstView.ItemsSource = lst;
    }

    private void BuildList()
    {
        lst = new List<MyModel>();
        for (int i = 0; i < 10; i++)
        {
            MyModel mod = new MyModel();
            mod.Id = i;
            mod.Desc = "Desc" + i.ToString();
            mod.Children = new List<MyModel>();

            for (int j = 100; j < 102; j++)
            {
                MyModel mod2 = new MyModel();
                mod2.Id = j;
                mod2.Desc = "Desc" + j.ToString();
                mod2.Children = new List<MyModel>();
                for (int k = 1000; k < 1002; k++)
                {
                    MyModel mod3 = new MyModel();
                    mod3.Id = k;
                    mod3.Desc = "Desc" + k.ToString();
                    mod3.Children = new List<MyModel>();
                    mod2.Children.Add(mod3);
                }
                mod.Children.Add(mod2);
            }
            lst.Add(mod);
        }
    }
}

Upvotes: 1

Related Questions