WinUI Stuff: How to use a Data Template Selector for ListView or GridView Controls (C++) – Part II

Part II

What is in for you?

In Part I of this “How To” we learned how easy it is to create a list using the ListView control of WinUI. But the promising headline was “how to use a Data Template selector” and honestly, yes, we used a data template, but we did not use a SELECTOR at all. So, finally we learned how to set up a list rather quickly and we saw how easy it is to style the items using XAML. But I promised that it is also easy to style each item INDIVIDUALLY. And that is exactly where a data template SELECTOR comes into play.

In this tutorial you will learn about:

  • Reusing a <DataTemplate> within a <ContentControl>
  • Using static resources as defined in the WinUI3 gallery
  • Using a data template selector

What we will reach within this How To:

You should have read Part I of this how to, since we will extend that code we will mainly rely on the concepts there.

You will find the code in my GitHub repositories: https://github.com/AgentSmith-Dev/How2-WinUI

Further reading: https://learn.microsoft.com/en-us/windows/apps/design/controls/data-template-selector

The principle

When we used the <ListView> attribute ItemTemplate in Part I we established a 1:1 relationship between an item in the control and the <DataTemplate> to be used for rendering.

If we have more than one template available, we additionally need something in between. That is where the data template selector comes into play:

The look of the nucleotides

Let’s start, where good concepts usually start: with the customer experience. Let’s design the look (&feel) of the nucleotides first. Currently we focus on the part “look” – there is not so much “feel” (yet!) in – we will improve that in one of the later “How Tos”. But even though we want to have a different look for each nucleotide we do not want to have them entirely different. Therefore, we keep the main look of a nucleotide from the first part. Each nucleotide is represented by a large capital letter:

<!--    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    -->
<!--    A Nucleotide -->
<!--    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    -->
  <DataTemplate x:Key="resNucleotide" x:DataType="local:clWinUINucleotide">
      <StackPanel>
          <TextBlock Text="{x:Bind hstrSymbol_Property, Mode=OneWay}" 
                     Margin="5"
                     Style="{StaticResource   TitleTextBlockStyle}"
          />
      </StackPanel>
  </DataTemplate>

Have you noticed (already in Part I): there is no reason for the use of the <StackPanel> control. However, I usually start with a wrapping <StackPanel> control even though there might be only one control inside of it. But usually, an additional control will be added in the development process sooner or later and therefore I use to have it from the beginning. But if you were wondering about the purpose of the <StackPanel> in the design of the nucleotide in Part I, here is the answer: there is no reason.

In Part I each nucleotide had a border around its capital letter. You probably have noticed that this has been gone. Well, it’s time to start individualization and each nucleotide type will get its individual border with its individual border color. Let’s start with Adenine and we define an additional <DataTemplate> just for “Adenine”:

<!--    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    -->
<!--    The Adenine nucleotide -->
<!--    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    -->
<DataTemplate x:Key="resNucleotide_Adenine" x:DataType="local:clWinUINucleotide">
    <Border BorderThickness="2, 2, 2, 2"    
            Background="Orange"   
            BorderBrush="{StaticResource    ControlElevationBorderBrush}">
        <StackPanel Orientation="Vertical">
            <ContentControl ContentTemplate="{StaticResource resNucleotide}" 
                            Content="{x:Bind}"   
                            HorizontalAlignment="Center"
                            Width="Auto"/>
            <TextBlock    Width="Auto" Text="Adenine"
                          HorizontalAlignment="Center"
                          Style="{StaticResource   CaptionTextBlockStyle}"
                          Margin="2"
            />
        </StackPanel>

    </Border>

</DataTemplate>

The XAML is pretty much straightforward and there is not much to say about. Maybe with one exception: the <ContentControl>. I always think of the <ContentControl> as makro which “embeds” another control. That’s what happens here. The attribute ContentTemplate “embeds” our StaticResource resNucleotide. This way, we have one resource which will be used by each nucleotide, and they will all look the same.

We add the three remaining <DataTemplate>s for Cytosine, Guanine and Uracil. Check the code on GitHub if you want to have a deeper look at them.

And finally, we add a further <DataTemplate> for the defects in the RNA. That one is entirely different from the other templates:

<!--    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    -->
<!--    The Error nucleotide -->
<!--    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    -->
<DataTemplate x:Key="resNucleotide_Error" x:DataType="local:clWinUINucleotide">
    <Border BorderThickness="2, 2, 2, 2"    
            Background="{StaticResource SystemFillColorCriticalBackgroundBrush}"   
            BorderBrush="{StaticResource    SystemFillColorCriticalBrush}">
            <StackPanel Orientation="Vertical">
                <TextBlock  Width="Auto" Text="Error"
                            HorizontalAlignment="Center"
                            Margin="2"
                            Style="{StaticResource    BodyStrongTextBlockStyle}"
                />
            </StackPanel>
    </Border>
</DataTemplate>

Of course, there is no <ContentControl> here, because there is no need to show a letter for a nucleotide.

Let’s talk about styling according to Windows guidelines: WinUI Gallery Dev

You have probably noticed the StaticResources like SystemFillColorCriticalBackgroundBrush, ControlElevationBorderBrush and many more. Theres are resources defined by Windows. You may find them in a file called Generic.XAML which is automatically included by the framework. But where do you know from, which resources to use. Here comes the WinUI3 Gallery Dev into play.

The WinUI Gallery is part of the Windows App SDK (you can even find the source code on GitHub) and it gives examples of the controls available in WinUI. The WinUI gallery also includes a “Design Guidance”. There you can find the colors, the typography, etc. which shall be used for the different purposes.

Connect the <ListView> with the <DataTemplate>

Now, we have a <DataTemplate> for each nucleotide and for a defect in place. How do we tell the <ListView> about the <DataTemplate>s? In Part I where we only had one <DataTemplate> and for that we used the ItemTemplate attribute of the <ListView>:

<!--    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    -->
<!--    Control to show the RNA (TAKEN FROM PART1) -->
<!--    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    -->
<ListView   x:Name="List_RNA"
            ItemsSource="{x:Bind  GetWinUIRNA_Page_Property.Get_obsvecRNA_Property, Mode=OneWay}"
            ItemTemplate="{StaticResource resNucleotide}"   
            Width="100"
>
</ListView>
How we attached to the data template to the list view in Part I

Since we now have five different <DataTemplate>s to be chosen from, we need some additional magic, a “Selector” is required which tells the <ListView> which template to use:

<!--    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    -->
<!--    Control to show the RNA -->
<!--    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    -->
<ListView   x:Name="List_RNA"
        ItemsSource="{x:Bind
                   GetWinUIRNA_Page_Property.Get_obsvecRNA_Property, Mode=OneWay}"
        ItemTemplateSelector="{StaticResource
                              Key_WinUI_DataTemplateSelector_RNA_Nucleotids}"
        Width="100"
                
>
</ListView>
XAML

You can see the DataTemplate-Selector is implemented as a resource (you see it by the “StaticResource” statement) and it obviously can be found it under “Key_WinUI_DataTemplateSelector_RNA_Nucleotids”:

<!--    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    -->
<!--    Data template selector to be used to display the nucleotids -->
<!--    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    -->
<local:clWinUI_DataTemplateSelector_RNA_Nucleotids
    
        x:Key="Key_WinUI_DataTemplateSelector_RNA_Nucleotids"
    
        Adenine_Property="{StaticResource resNucleotide_Adenine}"
        Cytosine_Property="{StaticResource resNucleotide_Cytosine}"
        Guanine_Property="{StaticResource resNucleotide_Guanine}"
        Uracil_Property="{StaticResource resNucleotide_Uracil}"
        Error_Property="{StaticResource resNucleotide_Error}"
/>
clWinUIControl_RNAList.xaml

The name of the resource is defined in its x:key statement. Further on you will find the names of the five resources for the nucleotides which we created above: resNucleotide_Adenine, resNucleotide_Cytosine, resNucleotide_Guanine, resNucleotide_Uracil, resNucleotide_Error. Each of these templates is connected to a code behind function: Adenine_Property, Cytosine_Property, Guanine_Property, Uracil_Property, Error_Property.

The data template selector is implemented like a custom control. All the logic needed is wrapped up in a custom WinUI class, called clWinUI_DataTemplateSelector_RNA_Nucleotids.

How to implement our data template selector

namespace How2_PartII_DataTemplateSelector
{
        runtimeclass    clWinUI_DataTemplateSelector_RNA_Nucleotids : Microsoft.UI.Xaml.Controls.DataTemplateSelector
        {
            clWinUI_DataTemplateSelector_RNA_Nucleotids();

            Microsoft.UI.Xaml.DataTemplate    Adenine_Property;
            Microsoft.UI.Xaml.DataTemplate    Cytosine_Property;
            Microsoft.UI.Xaml.DataTemplate    Guanine_Property;
            Microsoft.UI.Xaml.DataTemplate    Uracil_Property;
            Microsoft.UI.Xaml.DataTemplate    Error_Property;

        }
}
clWinUI_DataTemplateSelector_RNA_Nucleotids.idl

Obviously, there is not much to do. We need to define the code behind to gain access the data templates. Everything else is brought by the base interface Microsoft.UI.Xaml.Controls.DataTemplateSelector.

What is the purpose of these functions? The framework will call the setter version during the initialization of the control which uses the template selector. The setter gets an “interface” to the data template itself. The setter only needs to store it for later use (here the setter and the getter for Adenine):

C++
//  ------------------------------------------------------------------------------
/*! \brief  getter/setter for adenine data template
*   \date   08/26/2025  AGS Start
*/
//  ------------------------------------------------------------------------------
winrt::Microsoft::UI::Xaml::DataTemplate clWinUI_DataTemplateSelector_RNA_Nucleotids::Adenine_Property()
{
    return  m_DataTemplate_Adenin_Property;
}
void clWinUI_DataTemplateSelector_RNA_Nucleotids::Adenine_Property(winrt::Microsoft::UI::Xaml::DataTemplate const& value)
{
    m_DataTemplate_Adenin_Property=value;

    return;
}

These interfaces need to be stored somewhere. Therefore, we add a member for each item in the header file of the selector:

C++
protected:
        Microsoft::UI::Xaml::DataTemplate m_DataTemplate_Adenin_Property;
        Microsoft::UI::Xaml::DataTemplate m_DataTemplate_Cytosine_Property;
        Microsoft::UI::Xaml::DataTemplate m_DataTemplate_Guanine_Property;
        Microsoft::UI::Xaml::DataTemplate m_DataTemplate_Uracil_Property;
        Microsoft::UI::Xaml::DataTemplate m_DataTemplate_Error_Property;
clWinUI_DataTemplateSelector_RNA_Nucleotids.h

If you have look at the header file you will find a function that has been created by the framework: SelectTemplateCore(). The framework calls this function whenever an item in the <ListView> control (some for <GridView> control) is being rendered. The function gets an IInspectable interface of the item. In a first step we need to “cast” the IInspectable interface to a nucleotide:

C++
        clWinUINucleotide   rWinUINucleotide;
        if ((item.try_as<clWinUINucleotide>(rWinUINucleotide))) {
clWinUI_DataTemplateSelector_RNA_Nucleotids.cpp

Then we need to decide which <DataTemplate> is to be used. Our nucleotides have a “Type” property so we can easily implement a switch() statement. Depending on the type we return the appropriate interface to the <DataTemplate> which we stored above:

C++
//  ------------------------------------------------------------------------------
/*! \brief  called by the framework: the the template according the item to be
            inspected
*   \date   08/26/2025  AGS Start
*/
//  ------------------------------------------------------------------------------
winrt::Microsoft::UI::Xaml::DataTemplate clWinUI_DataTemplateSelector_RNA_Nucleotids::SelectTemplateCore(winrt::Windows::Foundation::IInspectable const& item)
{
    winrt::Microsoft::UI::Xaml::DataTemplate  rDataTemplate;

    clWinUINucleotide   rWinUINucleotide;
    if ((item.try_as<clWinUINucleotide>(rWinUINucleotide))) {
        switch (rWinUINucleotide.enNucleotide_Type_Property()) {
        case    winrt::How2_PartII_DataTemplateSelector::enNucleotide_Type::Adenine: {
            rDataTemplate = Adenine_Property();
            break;
        }
        case    winrt::How2_PartII_DataTemplateSelector::enNucleotide_Type::Cytosine: {
            rDataTemplate = Cytosine_Property();
            break;
        }
        case    winrt::How2_PartII_DataTemplateSelector::enNucleotide_Type::Guanine: {
            rDataTemplate = Guanine_Property();
            break;
        }
        case    winrt::How2_PartII_DataTemplateSelector::enNucleotide_Type::Uracil: {
            rDataTemplate = Uracil_Property();
            break;
        }
        default: {
            rDataTemplate = Error_Property();
        }
        }   //  endswitch (rWinUINucleotide.enNucleotide_Type_Property()) {
    }
    else{
        rDataTemplate = Error_Property();

		}   //  endif (item.try_as<clWinUINucleotide>(rWinUINucleotide)) {e


    return  rDataTemplate;
}
clWinUI_DataTemplateSelector_RNA_Nucleotids.cpp

And that’s it (almost, see the final trick below).

The two versions of SelectTemplateCore()

If you look at the code, you will find two versions of SelectTemplateCore()which are just slightly different. One version has an additional parameter dp which is a DependencyObject.

So, where do we implement our switch() statement? Or to be precise, which version is called by the framework? Microsoft’s online documentation is not very clear about it. It turns out that in most of the cases, if you have a <ListView> control (<GridView> contro) from which you want to select a <DataTemplate> the version with one parameter is the right one. The version with two parameters is never being called.

If you have a <ContentControl> which uses a data template selector with the attribute ContentTemplateSelector=”…” instead, then the version with two parameters is being called. You can test this yourself if you make things a bit more complicated and use a <ContentControl> with a ContentTemplateSelector instead of using a DataTemplateSelector directly:

C++
<!--    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    -->
<!--    Control to show the RNA / Deprecated version using ContentControl -->
<!--    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    -->
<ListView   x:Name="List_RNA"
            ItemsSource="{x:Bind       
              GetWinUIRNA_Page_Property.Get_obsvecRNA_Property, Mode=OneWay}"
            Width="100"
>
  <ListView.ItemTemplate>
    <DataTemplate>
      <ContentControl  Content="{Binding}"  
                       ContentTemplateSelector="{StaticResource    
                          Key_WinUI_DataTemplateSelector_RNA_Nucleotids}"
      />
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

 
Use the two-parameter-version of SelectCore()

The output of the RNA remains the same.

Don’t forget the final trick

If you compile the project you usually get an error like:

error C2039: 'clWinUI_DataTemplateSelector_RNA_Nucleotids': is not a member of 'winrt::How2_PartII_DataTemplateSelector::implementation'
error message

The code behind of the custom control which implements the data template selector needs to be aware of the implementation of the data template selector. Therefore, we add an include statement to the header of clWinUIControl_RNAList.h.

C++
#pragma once

#include "clWinUIControl_RNAList.g.h"

#include    "clWinUIRNA.h"
#include    "clWinUI_DataTemplateSelector_RNA_Nucleotids.h"
clWinUIControl_RNAList.h

Unfortunately, this is not very obvious. WinRT creates a lot of code by itself. As a matter of fact, we program only a small part of our WinUI classes. The rest is being added automatically by the framework. And it is obvious that the control needs know about the data template selector, unfortunately we can see it in “our” code. We only can see it by looking at the generated code.

Summary

Let’s summarize the major thoughts:

  • While we have a 1:1 relationship between item and template if we use the ItemTemplate attribute, we create a 1:n relationship by using the attribute ItemTemplateSelector. That selector makes the connection between the <ListViewItem> and the <DataTemplate>s.
  • A data template selector is defined as a separate XAML-resource by its key.
  • The data template selector is implemented through the interface Microsoft.UI.Xaml.Controls.DataTemplateSelector. Each <DataTemplate> we want to use gets its own getter/setter.
  • These setters are called by the framework during initialization of the <ListView>. Each setter gets an interface to the <DataTemplate>. The data template selector instance needs to store the interfaces.
  • We need to override the SelectTemplateCore() function which is being called by the framework when an item is going to be rendered to select the appropriate <DataTemplate>.
  • Don’t forget the #include statement in the header of the control (it’s being mentioned here because it might safe you hours of headache while searching for the problem…)

And that is our final result:

Where to go from here

We will extend our little RNA program a bit and add some functionality (the “feel” we talked in the introduction). Property change notifications are the mechanism to synchronize the UI and the internal data structures. In the end we will add some drag&drop functionality.

WinUI Stuff: How to use a Data Template Selector for ListView or GridView Controls (C++) – Part I

Part I

What is in for you?

The ListView control in XAML (<ListView>) is a great control to easily display elements in a list (let’s talk about its – I’d say even more powerful – sibling GridView in part II of the how to). Especially programmers who are used to select MFC for the UI can tell how hard it is to realize an individual styling for rows in a list control. Or even more challenging for the rows individually, depending on the content to be displayed. Using WinUI3 it is fairly easy to create the styling in XAML: you provide a template for an entry in a row and WinUI will do the rest.

This “How to” is split into two parts: in the first part I’d like to explain the basics how to make a list using the <ListView> control. In the second part we will extend the “How to” and add individual row design based on the type of the content to be displayed in a row.

In this tutorial you will learn about:

  • The WinUI control <ListView>
  • Using Data Templates in XAML with <DataTemplate>
  • Using a user defined control with <UserControl> (or <Page>)
  • Using the WinUI specific vector class “observable vector” (IObservableVector)

What we will reach within this How To:

You should be familiar with WinUI and how to create an app, as well as how to use auto generated code (from the MIDL compiler), etc. I will not discuss these steps in detail. For styling purposes, I use the WinUI Gallery.

I will use Visual Studio 2022 and C++ (version 17). By the time I write this how to, Microsoft is up to the (stable) Version 1.7250606001 of the WindowsAppSDK. I am using Windows 11.

You will find the code in my GitHub repositories: https://github.com/AgentSmith-Dev/How2-WinUI

An example from Biochemistry: display an RNA sequence

RNA (ribonucleic acid) is the name of a set of large molecules which play an essential role in in a lot of biological functions, mainly in the cell of plants, animals and human beings. Each RNA consists of four different types of molecules, called “nucleotides”: Adenosine (A), Cytosine (C), Guanine (G), Uracil (U). The sequence of these nucleotides is crucial for the functionality of the RNA.

Learn more about RNA: https://en.wikipedia.org/wiki/RNA

An RNA sequence is perfect for a list view example: we want to show an RNA sequence, just by displaying its nucleotids.

In the example we will display the microRNA rno-miR-21 from Rattus norvegicu, which is: 5′-UAGCUUAUCAGACUGAUGUUGA-3′.

Bring the biochemistry to C++

For the backbone of our example, we need two different classes:

clWinUINucleotide: represents a nucleotid. For the sake of simplicity its only member is the type of the nucleotide which we wrap up in an enumeration enNucleotide_Type.

clWinUIRNA: represents an RNA sequence. Since an RNA sequence is always linear and does not have branches, a vector is perfect to store the instances of clWinUINucleotide. Unfortunately, WinUI is not really good in supporting the C++ std library. Instead WinUI is supplying (I’d almost say as we’re used to from Microsoft) its own version of a vector class (yes, there may be good reasons, why std::vector can’t be used in winrt, but it is kind of annoying anyway). We will use the template class IObservableVector which you will find in the winrt::Windows::Foundation::Collections namespace. Note that this class is NOT in the Microsoft namespace as you might expect since WinUI3 is using this namespace instead of the Windows namespace which WinUI2 did. Another vector class would be IVector. But we will use IObservableVector which is more convenient to be used within a list view control. We’ll talk about that later.

App Architecture and backbone

The architecture of our app is straightforward. The base implementation has been created by the project wizard of Visual Studio 2022:

App.xaml wrapping MainWindow.xaml wrapping clWinUIContrl_RNAList.xaml wrapping ListView

UI architecture of the app

We have an App class (and exactly one instance) which holds everything together. The app class creates an instance of the MainWindow class during startup. So, this class is a good place to store our RNA. There, you will find the member m_WinUIRNA which is an instance of clWinUIRNA. To display the RNA, MainWindow implements a user control clWinUIControl_RNAList.xaml. This is where you find the <ListView> control which will display our RNA with its nucleotides.

Further down you will see that clWinUIControl_RNAList requires access to the RNA. Therefore, MainWindow forwards a reference to the RNA to clWinUIControl_RNAList. This is being done in the XAML if MainWindow when clWinUIControl_RNAList is instantiated:

<Window
    x:Class="How2_DataTemplateSelector.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:How2_DataTemplateSelector"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Title="How2_DataTemplateSelector - Part I">

    <local:clWinUIControl_RNAList   GetWinUIRNA_Page_Property="{x:Bind  GetWinUIRNA_Window_Property}"/>
</Window>

Create the app

The main focus of this how to is to how to implement data templates and data template selectors. Therefore, I won’t go too much into detail about setting up the app from the beginning. Let’s just have a quick look at the major steps.

We use the project wizard to create a blank app:

The wizard will create the backbone of the app for you:

Let’s add our two biochemistry classes to the app. We first create the idl files, then let the compiler create the .cpp and .h files (remember: you will find those in the ${ProjectDir}/GeneratedFiles/sources/).

Finally, we need a (XAML) class to display the RNA. We create a user defined control which we will implement in Mainframe.xaml. Let’s the project wizard do the main work.

(if you look at my examples you will find that I did not use the “User Control” template but the “Blank Page” template, therefore you will find a <Page> control instead of a <UserControl>. For our example here it does not make a difference).

When this is done your solution explorer should have everything in place:

Implementing the user control to display the RNA

Let us implement the user control. Open the file clWinUIControl_RNAList.xaml and add the XAML sections.

In the resources section we will add a <DataTemplate> which will define the look of a single row:

<Page.Resources>
        <!--  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    -->
        <!--    A Nucleotide -->
        <!--  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    -->
        <DataTemplate x:Key="resNucleotide" x:DataType="local:clWinUINucleotide">
            <Border BorderThickness="2, 2, 2, 2"    
                    Background="{StaticResource CardBackgroundFillColorDefaultBrush}"   
                    BorderBrush="{StaticResource    ControlElevationBorderBrush}"
                    >
                <StackPanel Orientation="Vertical"  HorizontalAlignment="Center">
                    <TextBlock Text="{x:Bind hstrSymbol_Property, Mode=OneWay}" 
                        Margin="5"
                        Style="{StaticResource   TitleTextBlockStyle}"
                    />
                </StackPanel>
            </Border>

        </DataTemplate>
    </Page.Resources>

The <ListView> itself is rather short:

    <!--  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    -->
    <!--    Control to show the RNA -->
    <!--  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++    -->
    <ListView   x:Name="List_RNA"
                ItemsSource="{x:Bind     GetWinUIRNA_Page_Property.Get_obsvecRNA_Property, Mode=OneWay}"
                ItemTemplate="{StaticResource resNucleotide}"   
                Width="100"
    >
    </ListView>

What do we have here? We have the x:Name which does not have any function (yet). It is there for documentation purposes as well as for extensibility. Let’s skip the ItemsSource attribute for a moment and go to the ItemTemplate attribute. It tells the <ListView> control to use the template specified in the resource section with the name “resNucleotide” (which we defined before). When the program runs each <DataTemplate> will get a clWinUINucleotide-object as you can see in the x:DataType attribute when being rendered. How is this being done? Now we come to the real interesting part: the <ListView> control has an ItemsSource attribute which tells the control where to get the data from. We’re using dynamic binding with the x:Bind operation. The x:Bind statement is being followed by the name of the interface “GetWinUIRNA_Page_Property”. This is a “code behind” function in the clWinUIControl_RNAList implementation. It is declared in the .idl file:

namespace How2_DataTemplateSelector
{
    [default_interface]
    runtimeclass clWinUIControl_RNAList : Microsoft.UI.Xaml.Controls.Page
    {
        clWinUIControl_RNAList();
        clWinUIRNA  GetWinUIRNA_Page_Property;
    }
}

That function returns a clWinUIRNA object. So, using this function we have access to our RNA. That means access to the vector with the nucleotids is needed. This is exactly what the (see in the XAML above) interface “Get_obsvecRNA_Property” does. This is again a “code behind” function, now in the clWinUIRNA implementation. It is declared in the .idl file:

namespace	How2_DataTemplateSelector
{
	runtimeclass    clWinUIRNA : Microsoft.UI.Xaml.Data.INotifyPropertyChanged
	{
		clWinUIRNA();
		
		Windows.Foundation.Collections.IObservableVector<clWinUINucleotide>      Get_obsvecRNA_Property{ get; };

        void CreateAndAddNucleotide(Char wcSymbol);

	}
}

That is why we used IObservableVector to store our nucleotides. The XAML controls can directly access such a vector which is very convenient. As a programmer you do not need any overhead to use an IObservableVector together with XAML controls. Everything which is required is in the class built in. One pitfall because it is often forgotten and ends with an exception being thrown: you need to initialize the instance of the IObservableVector class (which is valid for all classes of the observable collection classes). 

C++
//  ------------------------------------------------------------------------------
/*! \brief  Constructor for clWinUIRNA
 *  \detail
 *  \date   08/22/2025  AGS Start
 */
//  ------------------------------------------------------------------------------
    clWinUIRNA::clWinUIRNA()
    {
        // Initialize the RNA vector
        m_obsvecRNA = winrt::single_threaded_observable_vector<winrt::How2_DataTemplateSelector::clWinUINucleotide>();
    }

That’s it. Summarized, the expression ItemsSource=“{x:Bind    GetWinUIRNA_Page_Property.Get_obsvecRNA_Property, Mode=OneWay}“ tells the <ListView> control that it can find a vector by calling GetWinUIRNA_Page_Property() and then Get_obsvecRNA_Property(). For each object in the vector the data template is being rendered. 

The Parameter “Mode=OneWay” advises the WinUI framework to update the <ListView> control if there is a change in the vector. Very convenient, isn’t it?!

Summary

Let us summarize the major thoughts

  • Each nucleotide of an RNA is represented by an instance of the clWinUINucleotide class.
  • We have a class which implements the RNA itself: clWinUIRNA.
  • The RNA-class has an IObservableVector which holds the nucleotides. The IObservableVector can be accessed from “outside” using the interface function Get_obsvecRNA_Property().
  • The visual representation of the RNA is done in the user control clWinUIControl_RNAList.xaml. The instance of the class has a reference to the RNA class clWinUIRNA. This reference can be accessed from “outside” using the interface function GetWinUIRNA_Page_Property().
  • The XAML of the user control clWinUIControl_RNAList.xaml uses the <ListView> control to display the nucleotides in a list. 
  • The visual representation of each nucleotide is defined in a <DataTemplate> resource in XAML.
  • The <ListView> control may access the IObservableVector using dynamic binding through its ItemSource property calling the interfaces GetWinUIRNA_Page_Property() and Get_obsvecRNA_Property().

And that is our final result:

Where to go from here?

In the second part of this how to, we will implement a “data template selector”. Using a data template selector we can have individual data templates. Using such a selector each nucleotide can have its own visual representation. And we will also add an “error nucleotide” which is a representation of invalid nucleotides.