Why can't I use {x:Bind {RelativeSource Self}} in a data template?


Answers

Let me more specifically answer this. There is only one possible data context to x:bind and that is the underlying class. On a page, it is the page (or the code-behind). In a data template, it is the backing class specified in the targettype property of the data template. As an aside, in a control template, x:bind is not supported at all - though it's only a matter of time.

All that is to say that the data context of x:bind is fixed, and depending on where it is being used, I can tell you the data context without looking at your XAML. Why so rigid? In part to make the code generation around it simpler. Also, to make the implementation simpler, too. In either case, this is a fixed rule, and RelativeSource, ElementName, and Source and not supported in x:bind.

This does not mean you cannot reference the relativesource self, you just have to do it with a specified x:name. You would do something like this <Tag x:Name="Jerry" Tag="Nixon" Text="{x:Bind Jerry.Tag}" />.

Why does that particular sample fail? Unlike {binding}, {x:bind} requires matching types, which means setting Text's string can be down-cast and set to Tag's object, but Tag's object cannot be up-cast and set to Text's string value. The take-away for you is using x:bind means your types must match.

I hope this helps get you further along.

Best of luck.

Question

If I use {x:Bind {RelativeSource Self}} in a data template, I get the following error while compiling:

Object reference not set to an instance of an object.

The idea is to pass the templated object to a property like a command parameter. Here is an example MainPage.xaml:

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

    <Page.Resources>
        <ResourceDictionary>
            <local:OpenItemCommand x:Key="OpenCommand"/>
        </ResourceDictionary>
    </Page.Resources>

    <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <ItemsControl ItemsSource="{x:Bind NewsItems, Mode=OneWay}">
            <ItemsControl.ItemTemplate>
                <DataTemplate x:DataType="local:NewsItem">
                    <StackPanel>
                        <Button Command="{x:Bind {StaticResource OpenCommand}}" CommandParameter="{x:Bind {RelativeSource Self}}">
                            <TextBlock Text="{x:Bind Title}"/>
                        </Button>
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </StackPanel>
</Page>

A simple model is defined in the code-behinde file MainPage.xaml.cs:

using System;
using System.Collections.ObjectModel;
using System.Windows.Input;
using Windows.UI.Xaml.Controls;


namespace XBindTest5 {

    public class NewsItem {
        public string Title { get; set; }
    }

    /// <summary>
    ///     command to open the item
    /// </summary>
    public class OpenItemCommand : ICommand {

        public event EventHandler CanExecuteChanged;

        public bool CanExecute(object parameter) {
            return true;
        }

        public void Execute(object parameter) {
            // ... example ...
        }
    }

    public sealed partial class MainPage : Page {

        public ObservableCollection<NewsItem> NewsItems { get; set; }
            = new ObservableCollection<NewsItem>(new[] {
                new NewsItem() { Title = "Item 1" },
                new NewsItem() { Title = "Item 2" } });

        public MainPage() {
            this.InitializeComponent();
        }
    }
}



Is it possible to use compiled binding (x:Bind) with Relative Source, Templated Parent

RelativeSource (with x:Bind) is not supported, therefore this particular scenario won't be possible (at the moment, at least).

Using TemplateBinding or standard Binding to TemplatedParent (as you mentioned) are workarounds.

TemplateBinding is already an optimized version of Binding so it shouldn't be that big of a deal according to this Build 2015 session by Sam Spencer.







Tags