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

查看:54
本文介绍了为什么不能在数据模板中使用{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 类作为其数据上下文并绑定<此类的code> NewsItems 属性为 ItemsSource .而在数据模板内部时, {x:Bind} 使用在 x:DataType 中声明的类作为其数据上下文.请注意 DataTemplate和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设计器中有一个小错误,您仍然可能会得到 Object引用未设置为对象实例的情况. 错误.您可以像 {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天全站免登陆