我的代码隐藏定义了一个带有属性和构造函数的简单类,如下所示:
public class Question
{
public string[] Answers
{
get; set;
}
public int CorrectAnswerIndex
{
get; set;
}
public Question(string[] answers, int correctIndex)
{
this.Answers = answers;
this.CorrectAnswerIndex = correctIndex;
}
}
然后存在一个这种类型的公共对象,它在窗口的构造函数中初始化,如下所示:
CurrentQuestion = new Question(
new string[] { "First", "Second", "Third", "Fourth" }, 2
);
然后我有以下XAML试图从所述问题中打印出所有可能的答案。
<Grid Margin="150,150,150,150" DataContext="local:CurrentQuestion">
<ListBox ItemsSource="{Binding Answers}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
本地名称空间以前被定义为CLR名称空间。
然而,我的名单显得空洞无物。运行时没有绑定错误。
这里发生了什么?这似乎是一个简单的例子,只是不会运行。我觉得我错过了一些“明显的东西”。
答案 0 :(得分:2)
对于名为ListBox.DataContext
的属性,我们会查看Answers
,并尝试将其用于ItemsSource
。
<ListBox ItemsSource="{Binding Answers}">
ListBox.DataContext
将从父Grid
继承。不幸的是,网格的DataContext
是一个字符串,字符串没有名为Answers
的属性。因此Binding
无法执行任何操作并为您提供null
。
<Grid Margin="150,150,150,150" DataContext="local:CurrentQuestion">
<ListBox ItemsSource="{Binding Answers}">
XAML隐式转换是Do-What-I-Mean的事情,因此是一个混乱的源头。有时您可以将local:CurrentQuestion
放在属性值中并将其作为数据类型 - 但这不是其中之一。并且数据类型不是您想要提供的。你想要一个名字的财产。但是local:
是一个名称空间,一个像System.Windows.Controls
这样的文字CLR名称空间,而不是对象的引用。
以下是UserControl
中的XAML如何绑定到UserControl
的属性。如果是Window
,请将UserControl
更改为Window
。
<Grid Margin="150,150,150,150">
<ListBox
ItemsSource="{Binding CurrentQuestion.Answers, RelativeSource={RelativeSource AncestorType=UserControl}}">
我只是猜测CurrentQuestion
是UserControl
的属性。如果它在其他地方,请告诉我。
更新CurrentQuestion
时,您可能还会遇到问题,除非它是依赖属性。如果它是这样的普通旧CLR属性,则在其值更改时不会通知UI:
public Question CurrentQuestion { get; set; }