在 ListBox 中使用 DataTemplate
假设我们有以下 XAML 片段:
<ListBox x:Name="MyListBox" />
然后在这个 XAML 文件的代码隐藏中,我们在构造函数中编写以下内容:
MyListBox.ItemsSource = new[]
{
1, 2, 3, 4, 5
};
运行应用程序,我们得到一个我们输入的数字列表。
但是,如果我们尝试显示自定义类型的对象列表,就像这样
MyListBox.ItemsSource = new[]
{
new Book { Title = "The Hitchhiker's Guide to the Galaxy", Author = "Douglas Adams" },
new Book { Title = "The Restaurant at the End of the Universe", Author = "Douglas Adams" },
new Book { Title = "Life, the Universe and Everything", Author = "Douglas Adams" },
new Book { Title = "So Long, and Thanks for All the Fish", Author = "Douglas Adams" },
new Book { Title = "Mostly Harmless", Author = "Douglas Adams" }
};
假设我们有一个名为 Book
的类
public class Book
{
public string Title { get; set; }
public string Author { get; set; }
}
然后列表看起来像这样:
虽然我们可以假设 ListBox 将足够智能来恰当地显示我们的书籍对象,但我们实际看到的是 Book
类型的全名。ListBox 实际上在这里做的是在它想要显示的对象上调用内置的 ToString()
方法,虽然在数字的情况下产生了理想的结果,但在自定义类的对象上调用 ToString()
会导致获得其类型的名称,如在截图上看到。
我们可以通过为我们的书类编写 ToString()
来解决这个问题,即
public override string ToString()
{
return Title;
}
但是,这不是很灵活。如果我们想要展示作者怎么办?我们也可以将它写入 ToString
,但如果我们不想在应用程序的所有列表中呢?如何展示漂亮的书籍封面?
这就是 DataTemplates 可以提供帮助的地方。它们是 XAML 的片段,可以根据需要实例化,根据创建的源数据填充详细信息。简单地说,如果我们扩展 ListBox 代码如下:
<ListBox x:Name="MyListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
然后列表将为其源中的每个项创建一个 TextBox
,这些 TextBox 将使用来自我们对象的 Title
属性的值填充其 Text
属性。
如果我们现在运行应用程序,我们将得到与上面相同的输出,*即使我们删除自定义 ToString
实现。对此有利的是,我们可以自定义此模板,远远超出简单的 string
(和 ToString
)的功能。我们可以使用我们想要的任何 XAML 元素,包括自定义元素,并且可以将它们的值绑定到来自对象的实际数据(如上例中的 Title
)。例如,按如下方式扩展模板:
<ListBox x:Name="MyListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock FontStyle="Italic" Text="{Binding Author}" />
<TextBlock FontSize="18" Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
然后我们得到了一个很好的格式化的书籍视图!