为什么我不能在数据模板中使用 {x:Bind {RelativeSource Self}}? [英] Why can't I use {x:Bind {RelativeSource Self}} in a data template?
问题描述
如果我在数据模板中使用 {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屋!