How to Bind to a DataTemplate in UWP
Tags: uwp, mvvm, binding, winui2
Published: 2022-05-19 17:07:11


First and foremost, you _can't_ bind to the outside context of a DataTemplate when using `x:Bind`, even so it is _highly_ recommended to use x:Bind for everything. You might argue that `Binding` will work for some cases, and that is true. However, if you are using MVVM, you don't want to use `Binding`, specially when working with Layouts in an `ItemsRepeater`, as it will not work in a predictable way. 

Now that we are on the same page, let's agree on two rules:
1. Every model (the type or class of the object) _must have_ all of the data and behavior properties that the data templates will use. That is also valid and specially important for things like visibility properties and other properties which will define how the component renders visually.
> NOTE: If you do not like this approach, you can always create a base class without any behavior property (e.g.: `Item`), and have a new class inherit from it where the rendering and behavior properties are then implemented (e.g.: `ItemViewModel`).  

2. Every data template must have a type associated to it. This not only will save you some time with suggestions when you are writing your `x:Bind`s, but without it you will most likely get typing errors related to the DataTemplate.

## Rendering a list of users
In this example we have a User model with some basic properties:
```C#
using System;

namespace MySolution.Domain.Models
{
    public class User
    {
        public Guid Id { get; set; }
        public string GivenName { get; set; }
        public string Surname { get; set; }
        public string DisplayName { get; set; }
        public string Mail { get; set; }
    }
}
```

The example below has an `ItemsRepeater` to render a list of users. Notice how the `DataTemplate` is configured outside of the `ItemsRepeater` and how we reference it as _static resource_. At first this might not look like a big deal, but besides better organizing the code, this will make a big difference when working with dynamic templates. 

```xml
<UserControl
    x:Class="MySolution.Controls.UsersList"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:models="using:MySolution.Domain.Models"
    xmlns:xamlc="using:Microsoft.UI.Xaml.Controls"
    mc:Ignorable="d">
	<UserControl.Resources>
		<DataTemplate x:Key="UserItemTemplate" x:DataType="models:User">
			<StackPanel>
				<TextBlock
					MaxWidth="180"
					FontWeight="SemiBold"
					Foreground="{x:Bind Foreground}"
					Text="{x:Bind User.DisplayName, Mode=OneWay}"
					TextTrimming="CharacterEllipsis" />
				<TextBlock
					MaxWidth="180"
					FontWeight="SemiLight"
					Foreground="{x:Bind Foreground}"
					Text="{x:Bind User.Mail, Mode=OneWay}"
					TextTrimming="CharacterEllipsis" />
			</StackPanel>
		</DataTemplate>
	</UserControl.Resources>

	<xamlc:ItemsRepeater
		ItemTemplate="{StaticResource UserItemTemplate}"
		ItemsSource="{x:Bind ItemsSource, Mode=OneWay}">
		<xamlc:ItemsRepeater.Layout>
			<xamlc:StackLayout x:Name="layout" Orientation="Vertical" />
		</xamlc:ItemsRepeater.Layout>
	</xamlc:ItemsRepeater>

</UserControl>
```

It is also important to highlight that we must explicitly declare the data type (`x:DataType="models:User"`), following the second rule mentioned before. 

Let me know if you have any questions or suggestions in the comments below.