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:
-
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
). 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:
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.
<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.
Top comments (1)
Really interesting.
Thanks for sharing!