为什么我不能在数据模板中使用 {x:Bind {RelativeSource Self}}? [英] Why can't I use {x:Bind {RelativeSource Self}} in a data template?

查看:15
本文介绍了为什么我不能在数据模板中使用 {x:Bind {RelativeSource Self}}?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我在数据模板中使用 {x:Bind {RelativeSource Self}},编译时会出现以下错误:

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.

这个想法是将模板化的对象传递给一个属性,比如命令参数.这是一个MainPage.xaml示例:

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>

在代码隐藏文件MainPage.xaml.cs中定义了一个简单的模型:

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();
        }
    }
}

推荐答案

虽然看起来你已经解决了你的问题,但我还是想做一些澄清,以避免混淆,让未来的读者清楚.

Although it seems you have solved your problem, I still want to make some clarifications to avoid confusion and make it clearly for future readers.

正如@Peter Duniho 提到的,{x:Bind} 不能使用 DataContext 属性,而 {x:Bind} 不能'没有 Source 属性,所以你不能在 {x:Bind} 中使用 StaticResource 作为数据上下文,但是你可以使用一个属性或静态路径.在使用 {x:Bind} 时,它使用背景类作为其数据上下文.例如,当您设置 ItemsSource="{x:Bind NewsItems, Mode=OneWay}" 时,它使用 XBindTest5.MainPage 类作为其数据上下文并绑定 XBindTest5.MainPage此类的 code>NewsItems 属性为 ItemsSource.而在 DataTemplate 中,{x:Bind} 使用在 x:DataType 中声明的类作为其数据上下文.请注意DataTemplate and x:DataType:

As @Peter Duniho has mentioned, {x:Bind} can't work with DataContext property and {x:Bind} doesn't have a Source property, so you can't use StaticResource as data context in {x:Bind}, but you can use a property or a static path instead. While using {x:Bind}, it uses the background class as its data context. For example, when you set ItemsSource="{x:Bind NewsItems, Mode=OneWay}", it uses the XBindTest5.MainPage class as its data context and bind the NewsItems property of this class to ItemsSource. And while inside a DataTemplate, {x:Bind} uses the class declared in x:DataType as its data context. Please note following explanation in DataTemplate and x:DataType:

DataTemplate(无论是用作项目模板、内容模板还是标题模板)内,Path 的值不会在页,但在被模板化的数据对象的上下文中.为了在编译时验证其绑定(并为它们生成高效的代码),DataTemplate 需要使用 x:DataType 声明其数据对象的类型.

Inside a DataTemplate (whether used as an item template, a content template, or a header template), the value of Path is not interpreted in the context of the page, but in the context of the data object being templated. So that its bindings can be validated (and efficient code generated for them) at compile-time, a DataTemplate needs to declare the type of its data object using x:DataType.

在您的情况下,您使用 DataTemplate 中的 Command,因此您可以在 NewsItem 中添加 OpenCommand 属性> 并将此属性绑定到 Command 以使用它.

In your case, you use the Command in DataTemplate, so you can add a OpenCommand property in NewsItem and bind this property to Command to use it.

在您的代码隐藏中:

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

在 XAML 中:

<DataTemplate x:DataType="local:NewsItem">
    <StackPanel>
        <Button Command="{x:Bind OpenCommand}" CommandParameter="{x:Bind}">
            <TextBlock Text="{x:Bind Title}" />
        </Button>
    </StackPanel>
</DataTemplate>

另外{x:Bind} 不支持{RelativeSource},通常你可以给元素命名并在Path 中使用它的名字作为备选.有关详细信息,请参阅 {x:Bind} 和 {绑定}特性比较.

Also {x:Bind} doesn't support {RelativeSource}, usually you can name the element and use its name in Path as an alternative. For more information see {x:Bind} and {Binding} feature comparison.

但是这不能在 DataTemplate 中使用,因为所有的 Path 都应该是 NewsItem 的一个属性.就您而言,我认为您要传递的是 NewsItem 而不是 Button,因此您可以使用 CommandParameter="{x:Bind}"NewsItem 作为 CommandParameter 传递.

But this can't be used in DataTemplate as all Path are supposed to be a property of NewsItem. And in your case, I think what you want to pass is the NewsItem not the Button, so you can use CommandParameter="{x:Bind}" to pass the NewsItem as the CommandParameter.

PS:XAML 设计器中存在一个小错误,您可能仍会收到未将对象引用设置为对象实例的错误..您可以像 {x:Bind } 一样在 Bind 之后添加一个空格作为解决方法.

PS: There is a small bug in XAML designer, you may still get a Object reference not set to an instance of an object. error. You can add a space after Bind like {x:Bind } as a workaround.

这篇关于为什么我不能在数据模板中使用 {x:Bind {RelativeSource Self}}?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆