数据绑定和列表
到目前为止,仅已使用数据绑定来显示和编辑一个对象的属性。 在本课中,你将应用数据绑定概念来显示对象集合。 为了简单起见,这些对象是颜色。 说得更清楚点就是,它们是多个 ColorDescriptor
类实例。
1.创建 ColorDescriptor
类
让我们创建一个类来表示颜色。 右键单击“解决方案资源管理器”中的“DatabindingSample
”项目,选择“添加”/“类”,再输入“ColorDescriptor
”作为类名。 选择“添加”,以创建此类。
ColorDescriptor
包含两个属性:作为 Windows.UI.Color
对象的颜色本身,以及颜色名称。 它还包含填充这些属性的构造函数、显示颜色名称的 ToString()
方法,以及 R、G 和 B 颜色成分的十六进制值。 下面是整个 ColorDescriptor
类。
using Windows.UI;
namespace DatabindingSample
{
public class ColorDescriptor : ObservableObject
{
public ColorDescriptor(Color color, string name)
{
Color = color;
Name = name;
}
public Color Color { get; private set; }
public string Name { get; private set; }
public override string ToString()
{
return $"{Name} (#{Color.R:X2}{Color.G:X2}{Color.B:X2})";
}
}
}
将 ColorDescriptor.cs 文件的默认内容替换为上面的代码。
2.创建 ColorList.xaml 页
为了显示颜色列表,我们将使用新的 XAML 页面。 右键单击“解决方案资源管理器”中的“DatabindingSample
”项目,并选择“添加”/“新建项”。 从可选项列表中选择“空白页面”,再输入“ColorList
”作为名称。 选择“添加”,以创建页面。
3.设置启动页面
现在,如果启动应用,打开的是“MainPage”页面。 由于将使用新建的 ColorList.xaml 页面,因此最好将它用作起始页面。 为此,请打开 App.xaml.cs,并找到负责导航到 MainPage 的代码行。
rootFrame.Navigate(typeof(MainPage), e.Arguments);
将 MainPage
替换为 ColorList
,并验证“ColorList”页面是否是应用的启动页面(按 F5 或选择“调试”/“开始调试”启动应用)。
4.创建用于颜色列表的逻辑
我们将继续采用前面介绍的最佳做法,即为新页单独创建逻辑。 所以,接下来将新建 ColorListLogic
类。
右键单击“解决方案资源管理器”中的“DatabindingSample
”项目,选择“添加”/“类”,再输入“ColorListLogic
”作为类名。 选择“添加”以创建此类,并将下面的代码粘贴到文件中:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Windows.UI;
namespace DatabindingSample
{
public class ColorListLogic : ObservableObject
{
public List<ColorDescriptor> LotsOfColors { get; private set; }
public ColorListLogic()
{
LotsOfColors = new List<ColorDescriptor>
{
new ColorDescriptor(Colors.Red, "red"),
new ColorDescriptor(Colors.White, "white"),
new ColorDescriptor(Colors.Green, "green"),
new ColorDescriptor(Colors.Yellow, "yellow"),
new ColorDescriptor(Colors.Blue, "blue"),
new ColorDescriptor(Colors.Black, "black")
};
}
}
}
ColorListLogic
类非常简单(目前)。 它有 LotsOfColors
属性,即 ColorDescriptor
对象的 List
。 在类的构造函数中,列表填充有一些颜色。 就是这样。
5.在 ListBox
中显示颜色
下一步是,在应用中显示颜色。 首先,先让 ColorListLogic
可通过 XAML 进行访问。 打开 ColorList.xaml.cs
,并将下面的代码添加到 ColorList
类中:
public ColorListLogic Logic { get; } = new ColorListLogic();
这里使用的语法与前面对 MainPageLogic
使用的相同。 它创建 get-only 属性,并将它的值初始化为新建的 ColorListLogic
对象。
接下来,打开 ColorList.xaml,并在 Grid
元素内添加以下 XAML。
<ListBox ItemsSource="{x:Bind Logic.LotsOfColors}"
Margin="20"
Width="200"
HorizontalAlignment="Left"
VerticalAlignment="Top"/>
其中有趣的是 ItemsSource
属性。 顾名思义,它提供 ListBox
中显示项的源。 它只绑定到 ColorListLogic
的 LotsOfColors
属性。
如果现在运行应用,应该会发现它在 ListBox
中显示颜色! 但看起来不太符合预期。 ListBox
似乎调用了 LotsOfColors
列表中存储的 ColorDescriptor
的 ToString()
方法。
6.定义项模板
最好有模板可显示 ColorDescriptor.Color
属性中存储的实际颜色及其名称。 如下图所示:
若要在 XAML 中对此进行编码,可以在 StackPanel
中放入有颜色的 Rectangle
和 TextBlock
。
<StackPanel Orientation="Horizontal">
<Rectangle Width="80" Height="20">
<Rectangle.Fill>
<SolidColorBrush Color="Blue"/>
</Rectangle.Fill>
</Rectangle>
<TextBlock Text="blue" Margin="20, 10, 0, 10"/>
</StackPanel>
这就是 XAML 和数据绑定的优势之一。 几乎所有复杂视觉对象所依据的模板都可重新定义。 必须将上面的 StackPanel
放入 DataTemplate
中,才能将它用作模板。 DataTemplate
需要定义 DataType
,即可向其应用模板的数据类型。 在此示例中,它是 ColorDescriptor
类。 所以,DataTemplate
如下所示:
<DataTemplate x:DataType="local:ColorDescriptor">
<!-- template content comes here -->
</DataTemplate>
数据在 ListBox
(以及其他许多控件)中的呈现方式受控于它的 ItemTemplate
(应设置为 DataTemplate
)。 有多种方法可实现此操作。 在本课中,只需使用以下语法,在 ListBox
中定义 DataTemplate
即可:
<ListBox ...>
<ListBox.ItemsSource>
<DataTemplate ...>
...
</DataTemplate>
</ListBox.ItemsSource>
</ListBox>
稍后将会介绍如何将 DataTemplate
定义为资源,从而在多个位置重用它。
现在整个 ListBox
如下所示(如果尚未跟着我一起操作,请将整个 <ListBox>
标记替换为下面的 XAML):
<ListBox ItemsSource="{x:Bind Logic.LotsOfColors}"
Margin="20"
Width="200"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<ListBox.ItemTemplate>
<DataTemplate x:DataType="local:ColorDescriptor">
<StackPanel Orientation="Horizontal">
<Rectangle Width="80"
Height="20">
<Rectangle.Fill>
<SolidColorBrush Color="{x:Bind Color}"/>
</Rectangle.Fill>
</Rectangle>
<TextBlock Text="{x:Bind Name}"
Margin="20, 10, 0, 10"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
请注意,因为 ListBox
中的每一项都对应于 ColorDescriptor
对象,所以只需在此类的上下文中定义模板内的绑定。 编译器甚至会检查 Logic.LotsOfColors
是否包含 ColorDescriptor
对象,以及 ColorDescriptor.Color
和 ColorDescriptor.Name
是否存在且类型是否正确。
7.运行应用
现在,按 F5 或选择菜单中的“调试”/“开始调试”,以运行应用。 应该会看到色彩缤纷的颜色列表。
如果在调试模式下启动 XAML 应用,可利用实时 XAML 编辑。 甚至无需停止应用或按保存按钮。 只需更改 XAML,正在运行的应用中就会立即反映大部分更改。 现在就试试。 将数据模板内 Rectangle
的 Width
和 Height
更改为 30,从而将颜色矩形变为方形。
这称为 XAML 热重载,它非常适用于微调应用中的布局和动画。
总结
本课介绍了在 ListBox
中显示多个项的基础知识。 具有类似用途的控件还有其他许多,如 ItemsControl
、ListView
和 GridView
。 但基本原则是相同的:将对象列表(IEnumerable
、List<>
)绑定到 ItemsSource
属性,并将 DataTemplates
定义为控制各个列表项的外观和行为方式。 还可以重新定义这些项的布局,甚至是容器控件本身的外观(尽管这超出了本模块范围)。
请注意,代码从来都不需要处理 ListBox
本身。 它只创建了业务对象集合 (ColorDescriptor
),而 XAML 运行时则负责展开每一项的模板。
下一课将介绍如何便于用户从 ListBox
或下拉列表中选择项,并更改代码中的列表内容,以便在 UI 中反映元素添加和删除。
到目前为止,仅已使用数据绑定来显示和编辑一个对象的属性。 在本课中,你将应用数据绑定概念来显示对象集合。 为了简单起见,这些对象是颜色。 说得更清楚点就是,它们是 ColorDescriptor
类的多个实例。
1.创建 ColorDescriptor
类
让我们创建类来表示颜色。 右键单击“解决方案资源管理器”中的“DatabindingSampleWPF
”项目,选择“添加”/“类”,再输入“ColorDescriptor
”作为类名。 选择“添加”,以创建此类。
ColorDescriptor
包含两个属性:作为 System.Windows.Media.Color
对象的颜色本身,以及颜色名称。 它还包含设置这些属性的构造函数、显示颜色名称的 ToString()
方法,以及 R、G 和 B 颜色成分的十六进制值。 下面是整个 ColorDescriptor
类。
using System.Windows.Media;
namespace DatabindingSampleWPF
{
public class ColorDescriptor : ObservableObject
{
public ColorDescriptor(Color color, string name)
{
Color = color;
Name = name;
}
public Color Color { get; private set; }
public string Name { get; private set; }
public override string ToString()
{
return $"{Name} (#{Color.R:X2}{Color.G:X2}{Color.B:X2})";
}
}
}
将 ColorDescriptor.cs
文件的默认内容替换为上面的代码。
2.创建 ColorList.xaml 页
为了显示颜色列表,我们将使用新的 XAML 文件。 右键单击“解决方案资源管理器”中的“DatabindingSampleWPF
”项目,并选择“添加”/“新建项”。 从可选项列表中选择“窗口(WPF)”,再输入“ColorList
”作为名称。 选择“添加”,以创建页面。
3.设置启动 XAML 文件
现在,如果启动应用,打开的是“MainWindow”页面。 由于将使用新创建的 ColorList.xaml
页面,因此最好让它在应用启动时显示。 为此,打开 App.xaml
,并找到根 Application
元素的 StratupUri
属性。
StartupUri="MainWindow.xaml"
将 MainWindow
替换为 ColorList
,并验证“ColorList”是否是应用的启动页面(按 F5 或选择“调试”/“开始调试”启动应用)。
4.创建用于颜色列表的 DataContext
我们将继续采用前面介绍的最佳做法,即为新 XAML 窗口单独创建 DataContext
类。 所以,我们接下来将创建一个新类,称为 ColorListDataContext
。
右键单击“解决方案资源管理器”中的“DatabindingSample
”项目,选择“添加”/“类”,再输入“ColorListDataContext
”作为类名。 选择“添加”以创建此类,并将下面的代码粘贴到文件中:
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Windows.Media;
namespace DatabindingSampleWPF
{
public class ColorListDataContext: ObservableObject
{
public List<ColorDescriptor> LotsOfColors { get; private set; }
public ColorListDataContext()
{
LotsOfColors = new List<ColorDescriptor>
{
new ColorDescriptor(Colors.Red, "red"),
new ColorDescriptor(Colors.White, "white"),
new ColorDescriptor(Colors.Green, "green"),
new ColorDescriptor(Colors.Yellow, "yellow"),
new ColorDescriptor(Colors.Blue, "blue"),
new ColorDescriptor(Colors.Black, "black")
};
}
}
}
ColorListDataContext
类非常简单(目前)。 它有 LotsOfColors
属性,即 ColorDescriptor
对象的 List
。 在类的构造函数中,列表填充有一些颜色。 就是这样。
5.在 ListBox
中显示颜色
下一步是,在应用中显示颜色。 如前面一样,我们需要在 ColorList.xaml
中创建 ColorListDataContext
类的一个实例,并将它设置为整个窗口的 DataContext
。 打开 ColorList.xaml
,并紧跟在 <Window ...>
标记后添加下面的代码:
<Window.DataContext>
<local:ColorListDataContext/>
</Window.DataContext>
此时,需要编译代码,以便 XAML 设计器能够解决新定义的 ColorListDataContext
类。
然后,在 <Grid>
标记内复制以下 XAML 标记:
<ListBox ItemsSource="{Binding LotsOfColors}"
Margin="20"
Width="200"
HorizontalAlignment="Left"
VerticalAlignment="Top"/>
其中有趣的是 ItemsSource
属性。 顾名思义,它提供 ListBox
中显示项的源。 它只绑定到 ColorListDataContext
的 LotsOfColors
属性。
如果现在运行应用,应该会发现它在 ListBox
中显示颜色! 但看起来不太符合预期。 ListBox
似乎调用了 LotsOfColors
列表中存储的 ColorDescriptor
的 ToString()
方法。
6.定义项模板
最好有模板可显示 ColorDescriptor.Color
属性中存储的实际颜色及其名称。 如下图所示:
若要在 XAML 中对此进行编码,可以在 StackPanel
中放入有颜色的 Rectangle
和 TextBlock
。
<StackPanel Orientation="Horizontal">
<Rectangle Width="80" Height="20">
<Rectangle.Fill>
<SolidColorBrush Color="Blue"/>
</Rectangle.Fill>
</Rectangle>
<TextBlock Text="blue" Margin="20, 10, 0, 10"/>
</StackPanel>
这就是 XAML 和数据绑定的优势之一。 几乎所有复杂视觉对象所依据的模板都可重新定义。 必须将上面的 StackPanel
放入 DataTemplate
中,才能将它用作模板:
<DataTemplate>
<!-- template content comes here -->
</DataTemplate>
数据在 ListBox
(以及其他许多控件)中的呈现方式受控于它的 ItemTemplate
(应设置为上面的 DataTemplate
)。 有多种方法可实现此操作。 在本课中,只需使用以下语法,在 ListBox
中定义 DataTemplate
即可:
<ListBox ...>
<ListBox.ItemsSource>
<DataTemplate ...>
...
</DataTemplate>
</ListBox.ItemsSource>
</ListBox>
稍后将会介绍如何将 DataTemplate
定义为资源,从而在多个位置重用它。
现在整个 ListBox
的标记如下所示(如果尚未跟着我一起操作,请将整个 <ListBox>
元素替换为下面的 XAML):
<ListBox ItemsSource="{Binding LotsOfColors}"
Margin="20"
Width="200"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Width="80"
Height="20">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding Color}"/>
</Rectangle.Fill>
</Rectangle>
<TextBlock Text="{Binding Name}"
Margin="20, 10, 0, 10"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
请注意,因为 ListBox
中的每一项都对应于 ColorDescriptor
对象,所以只需在此类的上下文中定义模板内的绑定。
7.运行应用
应该会立即在 Visual Studio 中看到颜色列表。 只是确保一下,现在按 F5 或选择菜单中的“调试”/“开始调试”,以运行应用。
如果在调试模式下启动 XAML 应用,可利用实时 XAML 编辑。 甚至无需停止应用或按保存按钮。 只需更改 XAML,正在运行的应用中就会立即反映大部分更改。 现在就试试。 将数据模板内 Rectangle
的 Width
和 Height
更改为 30,从而将颜色矩形变为方形。
这称为 XAML 热重载,它非常适用于微调应用中的布局和动画。
总结
本课介绍了在 ListBox
中显示多个项的基础知识。 具有类似用途的控件还有其他许多,如 ItemsControl
、ListView
和 GridView
。 但基本原则是相同的:将对象列表(IEnumerable
、List<>
)绑定到 ItemsSource
属性,并将 DataTemplate
定义为控制各个列表项的外观和行为方式。 还可以重新定义这些项的布局,甚至是容器控件本身的外观(尽管这超出了本模块范围)。
请注意,逻辑代码从未对 ListBox
控件有任何了解。 它只创建了业务对象集合 (ColorDescriptor
),而 XAML 运行时为每个项处理了模板的呈现。
下一课将介绍可以如何从 ListBox
或 ComboBox
中选择项,并更改代码中的列表内容,以便在 UI 中反映元素添加和删除。