7.4.6 ListView(1)
ASP.NET 3.5引入了一个新的数据绑定列表控件ListView。ListView控件主要用于提供一个数据绑定控件,弥补ASP.NET 2.0中高度结构化的GridView控件和未结构化的DataList和Repeater控件之间的空白。
过去,许多需要栅格样式的数据控件的开发人员选择GridView,是因为GridView便于使用,提供了强大的功能,例如数据编辑、分页和排 序。但开发人员越钻研这个控件,就越觉得极难控制它显示HTML输出的方式。如果要减少控件生成的标记代码量,或者单独使用CSS控制控件的布局和样式, 就很成问题 。
另一方面,许多开发人员选择使用DataList或Repeater ,因为他们可以通过改进的控件控制显示。这两个控件不包含布局功能,需要开发人 员从头开始布置数据。但是,这两个控件缺乏GridView的一些基本功能,例如分页和排序,Repeater缺乏数据编辑功能。
ListView试图填补这些控件之间的空白。这个控件本身不在运行期间产生HTML标记,而是依赖11个不同的控件模板,这些模板表示控件的不同 区域和这些区域的可能状态 。在这些模板中,可以在设计期间放置控件自动生成的标记,或开发人员创建的标记,但在这两种情况下,开发人员仍可以全面控制控件 中各个数据项的标记以及整个控件的布局标记。另外,由于该控件能理解并处理数据的编辑和分页,所以可以让控件完成许多数据管理工作,开发人员可以把主要精 力集中在数据的显示上。
1. 开始使用ListView
要开始使用ListView,只需把该控件拖放到设计界面上,给它指定数据源,这与处理其他数据绑定的列表控件相同。但在指定了数据源后,并没有我 们期望的设计期间的布局预览。这是因为ListView默认没有定义布局,完全由开发人员定义该控件的布局 。事实上,该控件在设计期间的显示甚至说明,至 少需要定义ItemTemplate和LayoutTemplate,才能使用该控件。LayoutTemplate用作控件的根模 板,ItemTemplate用作控件是各个数据项的模板 。
定义ListView需要的模板时有两个选项。可以修改ListView智能标记中的Current View选项,直接编辑模板,也可以从该控件的智能标记中选择预定义的布局。改变Current View可以查看每个模板在运行期间的视图,直接编辑这些模板的内容,就好像编辑其他控件的模板一样。图7-31显示了ListView智能标记中的 Current View下拉列表。
第二个选项更简单,即从ConfigureListView对话框中选择预定义的布局模板。要打开这个对话框,只需单击智能标记中的 ConfigureListView选项。打开该对话框后,可以选择几个不同的预定义布局,选择几个样式选项,甚至配置基本操作选项,如编辑和分页。该对 话框如图7-32所示。
这个控件包含5个不同的布局类型:Grid、Tiled、Bulleted List、Flow和Single Row。它还包含4个不同的样式选项。每种类型的预览都显示在对话框中,改变当前选择的布局和样式,预览就会更新。
(点击查看大图)图 7-31 |
(点击查看大图)图 7-32 |
为 了说明这个控件是如何定义每个布局选项的,选择Grid布局和Colorful样式,并激活Inserting、Editing、Deleting和 Paging。单击OK,应用这些选择,关闭对话框。此时,应看到布局在设计期间的预览,运行页面会使ListView生成栅格布局,如图7-33所示。
(点击查看大图)图 7-33 |
ListView模板
一旦给ListView应用了一个布局模板,就会在Visual Studio的Source窗口中看到,为了提供布局,该控件生成了大量的标记。这些标记是根据Configure ListView对话框中的布局选项生成的。
仔细观察上一节为Grid布局生成的标记,会发现在默认情况下,控件创建了7个不同控件模板的标记:ItemTemplate、 AlternatingItemTemplate、SelectedItemTemplate、InsertItemTemplate、 EditItemTemplate、EmptyDataTemplate和LayoutTemplate。这些仅是该控件所带11个不同模板中的7个,也 可以使用它们为控件的不同状态提供标记。选择不同的预定义布局选项,会使控件生成不同的模板集合。当然,也可以手工添加或删除任意模板。所有11个模板如 表7-8所示。
表 7-8
模 板 名 称 | 说 明 |
ItemTemplate | 为控件中的每个数据项提供用户界面 |
AlternatingItemTemplate | 为控件中的隔行数据项提供独特的 UI |
SelectedItemTemplate | 为当前选中的数据项提供独特的 UI |
InsertItemTemplate | 为在控件中插入新数据项提供一个 UI |
EditItemTemplate | 为在控件中编辑已有的数据项提供一个 UI |
EmptyItemTemplate | 为当前页面的最后一组中没有要显示的数据时创建的行提供 UI |
EmptyDataTemplate | 绑定的数据对象不包含数据项时显示的模板 |
(续表)
模 板 名 称 | 说 明 |
LayoutTemplate | 该模板用作 ListView 的根容器,用于控制数据项的整体布局 |
GroupSeparatorTemplate | 用于提供组之间的分隔符 UI |
GroupTemplate | 用于为组合的内容提供独特的 UI |
ItemSeparatorTemplate | 用于在每个数据项之间提供分隔符 UI |
使用模板允许ListView控件保留组成ListView的标记部分和状态的许多基本信息,且仍可以全面控制ListView的UI。
ListView数据项的显示
ListView一般非常灵活,几乎可以完全控制其绑定数据的显示方式 ,但它有一些基本结构定义了上一节描述的模板之间的关系。如前所述,该控件至 少需要定义两个模板LayoutTemplate和ItemTemplate。LayoutTemplate是根控件模板,因此应在该模板中定义 ListView的数据项集合的整体布局。
例如,如果查看为Grid布局生成的模板标记,就会看到LayoutTemplate包含一个<table>元素定义、一个表行<tr>定义和为每个列标题定义的<td.>元素。
在ItemTemplate中应定义各个数据项的布局。如果再次查看为Grid布局生成的模板标记,会看到ItemTemplate是一个表行<tr>元素,后跟一系列包含实际数据的表单元格<td>元素。
ListView在显示时,ItemTemplate应显示在LayoutTemplate中,但需要一种机制告诉控件,在 LayoutTemplate的什么地方放置ItemTemplate。ListView控件在确定ItemTemplate在 LayoutTemplate中的位置时,会在LayoutTemplate中查找Item Container 。Item Container是一个HTML容器元素 ,并设置了runat="server" 属性,id属性为itemContainer(还是itemPlaceholder?以下同) 。该元素可以是任意有效的 HTML容器元素,但如果查看默认的Grid LayoutTemplate,会看到它使用<tbody>元素。
<tbody id="itemContainer"> |
为了增加控件的整体灵活性,甚至ListView查找的Item Container元素的id也是可以配置的。该控件默认尝试定位id属性设置为itemContainer的元素,但可以改变控件的ItemContainerID属性,来修改控件查找的id值。
如果控件没有找到适合用作Item Container的HTML元素,就抛出一个异常。
ListView使用标识为itemContainer的元素定位ItemTemplate和数据项级别的模板,例如 AlternatingItemTemplate、EditItemTemplate、EmptyItemTemplate、 InsertItemTemplate、ItemSeperatorTemplate和SelectedItemTemplate。在显示过程中,控件仅 根据所绑定的数据项的状态(选择、编辑或替换),把相应的项模板放在Item Container上。