How to x:Bind to xaml root object's member from DataTemplate in WinUI?

45 Views Asked by At

I try to bind to member of my Page in DataTemplate.

According this it should be possible to cast Page to my custom type. https://learn.microsoft.com/en-us/windows/uwp/xaml-platform/x-bind-markup-extension#casting

The binding in DataTemplate takes first the DataTemplate type but I can use the element name from my xaml tree as mentioned in above articel as well.

Nevertheless my root element is Page and I need to cast it to my custom type.

See the first sample:

<Page x:Class="PM.FantasyAdvisorNHL.Ui.Pages.TeamsPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:controls="using:PM.FantasyAdvisorNHL.Ui.Controls"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:local="using:PM.FantasyAdvisorNHL.Ui.Pages"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:models="using:PM.FantasyAdvisorNHL.Core.Models" x:Name="myPage"
      Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
      mc:Ignorable="d">
    <Page.Resources>
        <DataTemplate x:Name="myTemplate" x:DataType="models:Team">
            <controls:StatisticCellControl StatisticsMode="{x:Bind myPage.ViewModel.StatisticsModeViewModel.SelectedStatMode, Mode=OneWay}" />
        </DataTemplate>
    </Page.Resources>

</Page>

This will generate error WMC1110: Invalid binding path 'myPage.ViewModel.StatisticsModeViewModel.SelectedStatMode' : Property 'ViewModel' not found on type 'Page'.

Another sample code:

 <DataTemplate x:Name="myTemplate" x:DataType="models:Team">
     <controls:StatisticCellControl StatisticsMode="{x:Bind ((local:TeamsPage)myPage).ViewModel.StatisticsModeViewModel.SelectedStatMode, Mode=OneWay}" />
 </DataTemplate>

This will generate error CS1503: Argument 1: cannot convert from 'System.WeakReference' to 'Microsoft.UI.Xaml.Controls.Page'

So how can I access something from my page class in DataTemplate without using static?

If I use static function or static property as a workaround from code behind of my page how can I inform that the binding that something has changed and it should reevaluate value?

Thanks.

1

There are 1 best solutions below

2
mm8 On

Inside a DataTemplate with the x:DataType attribute set to models:Team, you can only use x:Bind to bind to members of the models:Team class. You cannot use compiled bindings to bind to properties of any other type or element, including the parent Page.

You may use an uncompiled binding using the {Binding} syntax though:

<Page x:Class="PM.FantasyAdvisorNHL.Ui.Pages.TeamsPage"
      ...
      Name="page">
    <Page.Resources>
        <DataTemplate x:Name="myTemplate" x:DataType="models:Team">
            <controls:StatisticCellControl
                StatisticsMode="{Binding ViewModel.StatisticsModeViewModel.SelectedStatMode,
                    ElementName=page}" />
        </DataTemplate>
    </Page.Resources>

</Page>

Or you could try this suggested workaround of using an attached property that sets the DataContext of the target element to a parent element of a specific type.