任务5. 2 图书信息浏览页面设计
②在后台代码文件中调用控件或页的DataBind方法进行数据绑定
虽然为TextBox1添加了绑定表达式,但运行后会发现并没有将值显示出来。这是由于没有在运行时对绑定表达式进行解析,需要调用控件的DataBind方法进行数据绑定后才能实现表达式的解析,每个Web控件都包含此方法。更为有效的是Page对象也包含此方法,只需调用一次Page对象的DataBind方法,就能实现页面上所有的子级控件的DataBind方法的调用。
例如,上例中在Page_Load事件中调用DataBind()的完整代码如下:
单值绑定实现较为简单,下面将以GridView为例详细介绍多记录绑定。
③网格控件(GridView)
GridView是一种典型的数据控件,它可以绑定到实现了IEnumerable接口的任何数据源(如DataTable、DataView、ArrayList或Hashtable等),也可以直接绑定数据源控件,关于数据源控件的内容将在“拓展与提高”部分进行介绍。GridView控件的功能非常丰富,它以表格的形式显示数据源的数据,能够设置数据显示的自定义样式,能够对数据进行排序、分页,还能够对数据源进行编辑和删除操作。
1)HTML代码
2)常用属性、外观样式属性、方法、事件
说明:GridView及其内部对象的常用属性较多,读者在学习时可以将属性分类以便于记忆,如用于设置样式的属性类,用于分页的属性类等。同时,当学习到GridView的使用时,会大量应用这些属性,这是最有效的加深对GridView属性理解的途径。
①常用属性
a.AllowPaging属性:设置或获取一个bool值,指示控件是否启用分页功能。
b.A llowSorting属性:设置或获取一个bool值,指示控件是否启用排序功能。
c.AutoGenerateColumns属性:设置或获取一个bool值,指示是否为数据源的每个字段自动创建绑定列,绑定列的概念将在后面介绍。
d.DataSource属性:获取或设置控件所绑定的数据源对象。
e.DataSourceID属性:获取或设置控件所绑定的数据源控件的ID。
f.DataKeyNames属性:该属性设置与GridView控件的主键绑定的数据源字段,可以是单个字段,也可以是多个字段。
g.DataKeys属性:获取一个由各行主键值构成的集合,一旦为GridView设置了主键后,可以通过该属性获取某行的键值。
h.A llowPaging属性:获取或设置一个bool值,指示是否启用分页功能。
i.PageSize属性:分页时控件每页显示出的记录条数。
j.PagerSettings属性:用于设置GridView控件的分页导航按钮的形式。
k.PageCount属性:获取分页显示时的总页数。
l.PageIndex属性:获取或设置分页显示时当前页的索引。
m.Show Footer属性:设置或获取一个bool值,指示是否在控件中显示脚注行。
n.ShowHeader属性:设置或获取一个bool值,指示是否在控件中显示题注行。
o.SortDirection属性:按某列排序的排序方向。
②外观样式属性
a.RowStyle属性:控件中一般数据行的样式设置。
b.A lternatingRowStyle属性:控件中交替数据行的样式设置,如设置了该属性,控件中的偶数行将使用交替行的样式显示。
c.EditRowStyle属性:控件中正在编辑的行的样式设置,当某行进入了编辑状态时,该行将呈现出该样式。
d.SelectedRowStyle属性:控件中被选中行的样式设置。
e.EmptyDataRowStyle属性:控件中显示空数据行的样式设置。
f.FooterStyle属性:脚注行的样式设置。
g.HeaderStyle属性:标题行的样式设置。
h.PagerStyle属性:分页导航区的样式设置。
③常用方法
a.DataBind方法:将数据源与控件相互绑定,绑定后,数据源和控件将同步变化。
b.FindControl方法:在当前的容器控件中搜索指定ID号的子控件,容器控件可以是GridView控件本身,也可以是控件的行、列或单元格。
c.Sort方法:根据指定的排序表达式和方向对GridView控件进行排序。
④常用事件
a.RowCommand事件:在控件中单击任何命令按钮执行任务时就会触发,包括行编辑命令和分页命令。
b.RowCreated事件:在控件中创建新行时触发。
c.RowDataBound事件:当控件逐行绑定数据源的数据时触发,GridView绑定方式是逐行绑定数据源的对应数据。
d.RowCancelingEdit事件:取消编辑状态时触发,即单击处于编辑状态的某行后面的“取消”按钮时触发。
e.RowDeleting事件:删除控件中某行时触发,即单击某行后面的“删除”按钮时触发。
f.RowEditing事件:当控件中某行进入编辑状态时触发,即单击某行后面的“编辑”按钮时触发。
g.RowUpdating事件:当控件中某行处于编辑状态,对单元格内容进行修改后,单击“编辑”按钮确认修改时触发。
h.Selected IndexChanging事件:当控件中被选行发生改变时触发,即单击非选中行的“选择”按钮时触发。
i.Sorting事件:当控件按某列进行排序时触发,即单击用于列排序的超链接时触发。
j.RowDeleted事件:控件中某行被删除后触发。
k.RowUpdated事件:对控件中某行进行更新后触发。
l.Selected IndexChanged事件:控件中被选中行发生改变后触发。
m.Sorted事件:当控件按列排序完成后触发。
3)GridView的列(对象)
GridView控件的列以对象的形式存在,有多种不同的类型,能用不同的形式显示数据;同时,不同类型的列具有共同的基类,因此它们相互之间又具有相似性,列(对象)的类型见表5.1。
表5.1 GridView列(对象)类型
下面将各种类型的列(对象)的常用属性及其使用方法进行说明。
①BoundField列
a.DataField属性:获取或设置要绑定到该列的数据源中字段的名称。
b.DataFormatString属性:获取或设置数据字段用于格式转换的格式化字符串。
c.HeaderText属性:获取或设置该列列头标题的文本。
d.NullDisplayText属性:当数据源字段值为空时,获取或设置默认的替代值。
e.ReadOnly属性:获取或设置一个bool值,指示该列的显示数据是否是能被修改的。
f.Control属性:该列中包含的Web控件集合,在某些状态下允许包含控件。
g.FooterText属性:获取或设置该列的页脚显示的文本。
h.HeaderStyle属性:获取或设置该列列头标题的样式。
i.Item Style属性:获取该列显示的数据的文本样式。
j.FooterStyle属性:获取或设置该列页脚的样式。
k.ControlStyle属性:获取该列所包含的Web控件的样式。
BoundField列通过DataField属性与数据源的某个字段相关联,并显示数据字段的文本信息,例如,如果GridView控件的某列要显示数据源的图书名称字段的信息,则GridView控件的HTML代码中必须包含声明该列的代码:
说明:dsBookName指该列关联的数据源中图书名称字段的名称。同时,也可以看到该列显示出来的列头标题是“书名”,而且,该列不允许进行编辑。
DataFormatString属性用于为该列文本的格式化显示指定格式化字符串,之前的C#语言课程应该介绍过格式化字符串的知识,这里只做简单回顾:格式化字符串通常包含占位符,占位符由位置指示符和格式指示器组成,并被包含在一组花括号中,如{0:F2},表示格式化为浮点数,并保留两位小数。格式化字符串广泛应用在数据控件中:可以用于转换数据控件所关联的数据字段值的格式,可以用于编写数据控件模板中的数据绑定表达式,还可以作为很多格式转换方法的参数等。
例如,希望GridView控件以短日期格式(如2013-3-20)显示图书的出版日期:
所有的列对象都有共同的基类,因此它们拥有很多公共的属性,下面在介绍其他列对象时只重点介绍列对象具有自身特点的独特属性。
②ButtonField列
可以看作是按钮与具有数据绑定能力的列的结合,下面介绍其独具特点的属性。
a.ButtonType属性:指该列显示的按钮样式,可以为普通按钮样式或超链接按钮样式。
b.CommandName属性:指定该列按钮关联的命令名,GridView控件的一行可以包含多个按钮,通过该属性可以在后台编码时判断是哪个按钮被单击。
c.DataTextField属性:指定该列的按钮文本要绑定的数据源字段的名称。
d.DataTextFormatString属性:指定按钮文本所绑定的数据源字段用于格式转换的格式化字符串。
e.Text属性:指定该列按钮将显示的静态文本,当没有对DataTextField属性进行设置时有效。
f.ImageUrl属性:指定该列按钮将显示的图像来源URL。
g.CausesValidation属性:是一个bool值,指示在单击列按钮时是否激发验证。
例如,如果GridView控件中的每条信息后都需要显示一个“加入购物车”按钮,则可以使用ButtonField列,该列的HTML代码如下:
说明:该列列头标题为“操作”,列中按钮为超链接样式,按钮文本没有绑定到数据源字段,显示为静态文本“加入购物车”,按钮的命令名为“AddCart”。
③CheckBoxField列
该列有以下几个重要的属性。
a.DataField属性:指定该列复选框所要绑定的数据源字段的名称,该数据源字段的值必须为bool型,控制复选框的是否被勾选。
b.Text属性:指定该列复选框旁显示的静态文本。
c.ReadOnly属性:指定该列复选框是否允许用户勾选。
例如,如果要使用该列显示某种图书是否还有库存,则该列的HTML如下:
说明:该列复选框与数据源的dsBookStocked字段相绑定,用复选框是否勾选表示某种图书的库存状态,该列的列头标题为“库存状态”,复选框旁边显示的文本为“有货”,该列复选框不允许用户勾选。
④HyperLinkField列
该列有以下几个重要的属性。
a.DataTextField属性:指定该列超链接显示文本所要绑定的数据源字段的名称。
b.DataTextFormatString属性:指定该列超链接显示文本所绑定的数据源字段用于格式转换的格式化字符串。
c.DataNavigateUrlFields属性:指定该列超链接跳转地址所要绑定的数据源字段的名称。
d.DataNavigateUrlFormatString属性:指定该列超链接的跳转地址所绑定的数据源字段用于格式转换的格式化字符串。
e.Text属性:指定该列超链接所显示的静态文本,当没有对DataTextField属性进行设置时有效。
f.NavigateUrl属性:指定该列超链接所跳转的静态URL地址,当没有对DataNavigateUrlFields属性进行设置时有效。
g.Target属性:指定跳转的目标网页所显示的目标窗口或框架。
例如,要制作这样一个超链接列,该列超链接显示文本是图书名称,单击图书名称在浏览器中显示该图书的封面图片(即跳转地址为该书封面图片的来源地址),则对应的HTML如下:
说明:该列超链接文本与数据源的bsBookName书名字段绑定,超链接跳转地址与数据源的bsImageFile封面图片文件名字段绑定,bsImageFile字段只包含封面图片的文件名信息,因此要使用格式化字符串转换成正确的相对路径。从代码中看到,该相对路径指向站点根目录下BookCover目录中与bsImageFile字段对应的封面图片。
⑤ImageField列
a.DataImageUrlField属性:指定该列图片来源URL所要绑定的数据源字段的名称。
b.DataImageUrlFormatString属性:指定该列图片来源URL所绑定的数据源字段用于格式转换的格式化字符串。
c.NullImageUrl属性:当数据源字段值为null时,所显示的默认图片的来源URL。
d.DataAlternateTextField属性:指定该列图片提示信息(当鼠标移至图片就会显示出来)所要绑定的数据源字段的名称。
e.DataAlternateTextFormatString属性:指定该列图片提示信息所绑定的数据源字段用于格式转换的格式化字符串。
f.AlternateText属性:指定该列图片的静态提示信息,当没有对DataAlternateTextField属性进行设置时有效。
g.NullDisplayText属性:指数据源字段值为null时显示在图片位置的替代文本。
例如,如果要使用该列显示某图书的封面图片,则该列的HTML如下:
说明:该列图片来源URL与数据源的bsImageFile图片文件字段相绑定,使用格式化字符串可将图片来源URL转换成相对路径,此相对路径指向站点根目录下BookCover目录中与bsImageFile字段对应的封面图片,并指定当图片文件字段无值时该列显示“没有上传封面图片”文本。
⑥CommandField列
CommandField列称为命令列,该列比较特殊,它会在不同的状态下显示执行删除、编辑、更新、取消或选择操作的命令按钮:该列在一般状态下显示“编辑”按钮、“删除”按钮、“选择”按钮,单击“编辑”按钮进入行编辑状态后,“编辑”按钮将由“更新”和“取消”按钮代替,“删除”和“选择”按钮会被隐藏,通过这些按钮的顺序显示并提供编程接口,GridView控件实际上是为用户提供了一套删除、更新、选择某行记录的操作规程。
该列的具体显示效果及如何对按钮编程会在后面介绍,下面介绍它的主要属性。
a.ShowDeleteButton属性:一个bool值,指示是否显示“删除”按钮,该按钮执行删除行操作。
b.ShowEditButton属性:一个bool值,指示是否显示“编辑”按钮,如果隐藏该按钮,就不能进入编辑状态,更不能执行“更新”和“取消”命令。
c.ShowSelectButton属性:一个bool值,指示是否显示“选择”按钮;该按钮执行选择行操作。
d.CancelText属性:用于设置或获取“取消”按钮的标题文本。
e.DeleteText属性:用于设置或获取“删除”按钮的标题文本。
f.EditText属性:用于设置或获取“编辑”按钮的标题文本。
g.SelectText属性:用于设置或获取“选择”按钮的标题文本。
h.UpdateText属性:用于设置或获取“更新”按钮的标题文本。
i.CancelImageUrl属性:指定“取消”按钮显示的图像来源地址。
j.DeleteImageUrl属性:指定“删除”按钮显示的图像来源地址。
k.EditImageUrl属性:指定“编辑”按钮显示的图像来源地址。
l.SelectImageUrl属性:指定“选择”按钮显示的图像来源地址。
m.UpdateImageUrl属性:指定“更新”按钮显示的图像来源地址。
例如,要在GridView控件显示的每条图书信息记录之后放置命令按钮,以执行对图书信息的编辑、删除和选择操作,则对应的HTML如下:
说明:该列会同时显示出“编辑”“删除”和“选择”按钮。一般情况下,命令列不用绑定到数据源字段,它的命令按钮的标题文本或图像也不用更改。
⑦TemplateField列
该列的作用是提供不同类型的模板,使用者通过在其中放入布局元素和Web控件实现自定义的用户界面(UI)。模板中的Web控件能与数据源的字段进行绑定,也能触发事件。
TemplateField列中(也称模板列)用于指定各种模板的属性最为重要。
a.Item Template属性:指定该列普通项(单元格)所显示的模板。
b.A lternatingItem Template属性:指定该列交替项所显示的模板,当指定了该属性后,奇数项为普通项,偶数项为交替项。
c.EditItem Template属性:指定进入编辑状态的项所显示的模板。
d.FooterTem p late属性:指定页脚显示的模板。
e.HeaderTemplate属性:指定列头标题显示的模板。
例如:使用模板列实现用文本框显示图书名称,对应的HTML代码如下:
说明:模板列只包含ItemTemplat项模板,项模板是为列中普通单元格定制的模板,最为常用,其内部放入了一个文本框控件TextBox1,文本框的Text属性被设置为“”,这是一个绑定表达式,与之前介绍的单值绑定略有差异的是:其中使用Eval()方法作为绑定表达式,该方法的作用是将Text属性与数据源的dsBookName字段绑定,使该列各单元格显示图书名称,关于模板中的Web控件的绑定表达式将在后面的内容中做进一步的介绍。
4)定制GridView的外观
VS 2008平台提供了定制GridView控件外观的向导工具,使开发者在大多数情况下无需人工编写GridView控件的界面HTML代码,在熟悉GridView控件的主要属性、方法以及列的概念和主要属性后,掌握该向导工具的使用是一件很容易的事情,下面将介绍如何使用向导工具实现GridView外观的定制。
①绑定数据源
绑定数据源是一项预备步骤,因为若要GridView能正常显示出来,必须为它绑定数据源,方法如下:
向Web页中拖放一个GridView控件到布局后的适当位置,设置该控件的ID号,也可以使用默认名称GridView1。
在代码文件的Page_Load事件处理方法中添加如下形式的代码。
这两句代码的含义是:使用DataSource属性为GridView控件设置数据源,然后调用DataBind方法进行数据绑定。在这两句代码之前应该还有从数据库查询数据,填充到数据集对象ds中的代码。ds如果是事件处理方法中的局部变量,说明编程者倾向于使用单向绑定,因为ds稍后就会被销毁,ds中的数据也会丢失,因此也就无法实施反向提交操作。在这种情况下,每次显示数据都需要从数据库查询数据并重新进行数据绑定,设计者通常会编写一个方法来实现查询和数据绑定过程,每次显示数据时都去调用该方法。以读者目前的基础,应该能够自行实现该方法。这里将该方法命名为ShowData(),在后面的代码中将直接使用。
实现这一步骤后便直接运行,可以看到,数据已经以一种原始表格形式显示出来,此时,数据源的字段名称自动成为GridView的列标题;数据源的字段信息全部显示为文本,即所有列都是BoundField类型的列,如图5.2所示。
图5.2 GridView的原始显示效果
关闭运行并切换回VS 2005开发平台后,发现属性面板中的AutoGenerateColumns属性被自动设置为True,这表明,在无人工干预的情况下,开发平台会自动为数据源所有字段创建对应的绑定列。
②添加列
要为GridView控件添加列,首先在属性面板中将控件的“AutoGenerateColumns”属性设置为False,关闭控件自动创建列的功能,然后单击控件右上角的“>”智能标记,在出现的下拉菜单中选择“添加新列”菜单项,弹出“添加字段”对话框,如图5.3所示。
图5.3添加BoundField列
在对话框的“选择字段类型”下拉列表控件中选择不同类型的列,则对话框的形式会有所不同,如选择HyperLinkField列,则对话框如图5.4所示。
在对话框中的其他输入控件中设置列的相关属性,例如,对于前面图示中的BoundField列,输入“页眉文本”实际是设置该列的HeaderText属性,输入“数据字段”实际是设置DataField属性,选中“只读”复选框实际是将ReadOnly属性设置为True;又如,对于前面图示的HyperLinkField列,输入“指定文本”实际是设置该列的Text属性,输入“指定URL”实际是设置NavigateUrl属性,当选择“从数据字段获取文本”单选按钮后,在其后文本框输入实际是设置DataTextField属性;当选择“从数据字段获取URL”单选按钮后,在其后文本框输入实际是设置DataNavigateUrlFields属性。
“添加字段”对话框实际是一个向导工具,通过字面分析基本能够找到该向导工具的输入项和列的属性之间的对应关系。另外,为检查这种对应关系是否正确,也可以切换到GridView控件所在页的源视图,查看向导工具自动生成的HTML代码。
当所有设置完成后,单击“确定”按钮关闭对话框,此时可以在编辑窗口中看到新列被创建后的效果。
③编辑列
选中GridView控件,单击控件右上角的“>”智能标记,在出现的下拉菜单中选择“编辑列”,弹出“字段”对话框,如图5.5所示。
在“选定的字段”列表框中以列标题的形式列出了目前所有的GridView控件中现存的列,当选中某个现存列后,在对话框右边的列表框会列出该列所对应的属性,我们可以在属性列表框中修改已设置的属性的属性值,或为未设置的属性设置值。在学习了列的主要属性后,读者应该对属性列表框中列出的主要属性不会感到陌生。即使对有些属性不清楚,还可以选中该属性,在属性列表框的下部查看对该属性的解释。
在“字段”对话框中,还能实现添加列的功能,只需在左上部的“可用字段”列表框中选择某种类型的字段,单击下面的“添加按钮”,就能在GridView控件现存列的最后添加一个新列,选中该列,就可以在右边的属性列表框中设置该列的属性。另外,“字段”对话框也支持列的其他操作:如果要删除某现存列,只需在“选定的字段”列表框中选中该列,单击列表框右边的图案为“×”的按钮;如果要改变某现存列在GridView中的位置,只需选中该列,单击列表框右边的上、下箭头按钮,即可实现列的上移和下移。
图5.4添加HyperLinkField列
图5.5编辑列对话框
④操作列
在GridView控件中选中某列,单击控件右上角的“>”智能标记,在出现的下拉菜单中,单击“左移列”菜单项可将选中列左移一个位置;单击“移除列”菜单项便可删除该列,如图5.6所示。
图5.6 GridView任务面板
也可以通过单击“编辑列”菜单项后,在弹出的“字段”对话框中实现改变列的位置和删除列操作,这在前面的“编辑列”内容中已做过介绍。
⑤样式定制
在前面已经介绍过,GridView控件自身和它的列都提供了很多控制样式的属性,为灵活的定制GridView的外观提供了便利。然而,要为GridView控件设计出一个美观的样式组合方案,对于大多数没有美工基础的开发者而言并不容易。因此,VS 2005平台为GridView控件提供了很多预设的样式方案供开发者选用,具体方法是:单击GridView控件右上角的“>”智能标记,在出现的下拉菜单中,选择“自动套用格式”菜单项,弹出“自动套用格式”对话框,左边“选择架构”列表框中列出了很多预设的样式方案,选中某种样式方案,右边会出现该样式方案的预览效果,单击“应用”按钮就能将样式方案应用到当前的GridView控件,单击“确定”按钮在应用样式方案后会关闭对话框,如图5.7所示。
图5.7 GridView自动套用格式对话框
⑥编辑模板
前面在介绍GridView的TemplateField列时,曾介绍过模板,实际上,模板的概念在ASP.NET中应用很广,几乎所有的数据控件都支持模板,例如这里介绍的GridView控件和后面将介绍的DataList控件和Repeater控件。使用模板能够定义数据控件的某些部分在某种状态下的外观和布局,如普通状态的标题、脚注、普通项和交替项;编辑状态下的编辑项;选择状态下的选中项等。可以为GridView控件指定模板,包括无数据时显示的模板(EmptyDataTemplate)和分页命令区模板(PagerTempate);还可以为GridView的TemplateField列指定模板,包括标题模板(HeaderTemplate)、脚注模板(FooterTemplate)、项模板(ItemTemplate)、交替项模板(AlternatingItemTemplate)和编辑项模板(EditItemTemplate)。其中,项模板、交替项模板和编辑项模板使用较多。这些模板作为GridView或TemplateField的属性而存在。
VS 2005同样为用户提供了使用模板的向导工具,这里将重点介绍如何为TemplateField创建模板,TemplateField列的模板必须在TemplateField存在的情况下才有效。因此,首先要添加TemplateField列,然后,单击GridView控件右上角的“>”智能标记,在出现的下拉菜单中选择“编辑模板”菜单项,进入模板编辑状态,此时,GridView控件会显示出模板编辑区,其智能下拉菜单也有所变化,如图5.8所示。
图5.8 GridView模板编辑状态
在“显示”下拉列表框中,列出了目前能被使用的所有的模板类型,如图5.9所示。从中可看到模板列的信息,如图中所示的Column[1]表示GridView的第1列是模板列,通过列和模板的关联,用户能准确地知道当前被选中的模板属于哪个列或是GridView控件本身。
图5.9 GridView选择模板类型
当选定某个模板后,就可以在左边GridView控件的模板编辑区放入Web控件进行模板列的界面布局,然后为Web控件的某些属性绑定数据源字段,下面使用实例进行说明。
例1在模板列中使用文本框显示图书名称信息。
选择对应列的项模板,在模板编辑区中放入一个TextBox控件,此时会发现TextBox控件右上角也出现了“>”智能标记,单击该标记,选择“编辑DataBindings...”,会弹出该控件的绑定对话框,如图5.10所示。
图5.10编辑DataBindings对话框
单击“刷新架构”按钮,将“字段绑定”部分的界面变为可用。此时,在对话框左部的“可绑定属性”列表框中选择Text属性,点选“自定义绑定”单选按钮,在“代码表达式”文本框中直接输入绑定表达式Eval(“bsBookName”);或者,点选“字段绑定”单选按钮,在“绑定到”下拉列表框中选择要绑定的数据源字段“bsBookName”。“字段绑定”可以看作是“自定义绑定”的向导方式。单击确定按钮关闭对话框,并完成数据绑定。
说明:Eval()是Page类的一个方法,它只能用于显示数据,因此,本实例采用的是单向绑定方式。Eval()有两种重载形式:
Eval(String):计算数据源的当前记录与参数相同的字段的值,参数为数据源字段名称。
Eval(String,String):使用指定的格式字符串计算数据绑定表示式的当前值,该值为当前记录的字段值替代格式字符串的占位符后得到的字符串,第1个参数为数据源字段名称,第2个参数为格式字符串。
很明显,本实例使用了Eval()方法的第1种重载形式。
例2在模板列中使用超链接显示图书名称,超链接的跳转地址为封面图片来源URL。
选择对应列的项模板,在模板编辑区中放入一个HyperLink控件,点开该控件右上角的“>”智能标记,选择“编辑DataBindings...”,弹出HyperLink控件对应的绑定对话框。
在左部的“可绑定属性”列表框中选择Text属性,在“代码表达式”文本框中输入Eval("bsBookName");然后,在“可绑定属性”列表框中选择NavigateUrl属性,在“代码表达式”文本框中输入Eval("bsImageFile","~\BookCover\{0}"),单击确定按钮完成数据绑定。
说明:本实例同时对HyperLink控件的两个属性进行绑定,其中,Text属性的绑定表达式使用了Eval()方法的第1种重载形式,NavigateUrl属性的绑定表达式使用了Eval()方法的第2种重载形式。
通过上述两个实例,学习了如何为模板列定制简单的用户界面并进行数据绑定。模板列的用户界面实际可能更复杂,可以包含多个Web控件,甚至可以包含表格、DIV等布局元素。
单击当前GridView控件的“>”智能标记,选择“结束模板编辑”命令,即可退出模板编辑状态,然后运行该网页,运行效果如图5.11所示。
图5. 11 书名模板列运行效果
HTML代码如下:
5)GridView的交互操作
GridView既支持数据绑定和模板编辑,也支持用户的交互操作,如分页操作、对数据库的反向操作以及自定义命令的操作,下面将分别予以介绍。
①分页操作
GridView控件内置了分页功能供开发者使用,只需进行一些属性设置和代码编写就能实现分页。GridView提供了下述的属性和事件用于支持开发者使用其内置的分页功能。
a.AllowPaging属性:指示是否允许分页。
b.PageIndex属性:当前页索引,默认为0。
c.PageSize属性:单页记录条数,默认为10。
d.PagerSettings属性:设置分页导航按钮的形式,包括以下子属性:
Mode属性:分页按钮的形式,可以设置为:
Numeric——页码导航,默认;
NextPrevious——上下页导航;
NextPreviousFirstLas t——上下页+首末页导航;
NumericFirstLast——页码+首末页导航。
FirstPageText属性:首页导航按钮显示的文本。
LastPageText属性:末页导航按钮显示的文本。
PreviousPageText属性:上一页导航按钮显示的文本。
NextPageText属性:下页导航按钮显示的文本。
PageIndexChanging事件:当前页码发生改变时触发。
GridView控件实现分页的过程比较固定:首先在控件对应的属性面板或后台代码中将AllowPaging属性设置为“True”,其他的分页属性可以根据需要进行设置或保持默认值,特别的是,设置分页导航形式使用PagerSettings属性的Mode子属性,设置分页导航按钮的文本使用PagerSettings属性的FirstPageText子属性、LastPageText子属性、PreviousPageText子属性和NextPageText子属性。然后,为PageIndexChanging事件生成事件处理方法并添加如下代码:
说明,第1条语句将用户导航后的页索引(从参数e的NewPageIndex属性中获取)作为GridView控件的当前页;第2条语句调用自定义方法ShowData()重新绑定数据源,在单向绑定的情况下,数据一旦发生变化都需要重新绑定数据源。
②对数据库的反向操作
GridView通过CommandField列为数据库的反向操作(删、改)提供了标准的接口和流程,下面将介绍如何实现这些操作。
A.为GridView添加一个CommandField,在命令按钮中选择“删除”“编辑/更新”“取消”按钮。
B.在GridView的属性面板为RowDeleting、RowEditing、RowUpdating、RowCancelingEdit,这4个事件的触发时机分别是单击某行的“删除”按钮时,单击某行的“编辑”按钮时,单击编辑状态下的某行的“编辑”按钮时,单击编辑状态下的某行的“取消”按钮时。
C.为这些事件处理方法添加代码,按其规定的流程实现对数据库的反向操作,下面分别给予说明。
a. RowDeleting事件处理方法的代码大致类似于这样:/得到该行的主键值
/使用主键值作为条件对数据库进行删除,代码省略
…
说明:从事件处理方法e的RowIndex属性中可以获取待删除的行的索引,通过该索引取得该行的主键值,以该值为条件,调用ADO.NET实现对数据库的删除操作,删除后,数据库的数据发生改变,调用ShowData()方法重新显示数据,该方法在前面已做过说明。
要获取当前行的主键值,则需要在之前进行数据绑定时对GridView的主键进行设置,用户可以在ShowData()方法中添加,例如,设置ISBN书号字段作为GridView的主键的代码为:
b. RowEditing事件处理方法的代码大致类似于这样:
说明:用从事件处理方法参数e中得到的用户想要编辑行的索引(NewEditIndex),用该行作为GridView控件的当前编辑行,即是使该行进入编辑状态。
c. RowUpdating事件处理方法的代码大致类似于这样:
说明:进入编辑状态的原来的数据将会以文本框的方式显示,使用户能进行修改。获取用于更新的用户的输入值的方法是:首先找到当前行(Rows[e.RowIndex]),再找到某单元格(Rows[e.RowIndex].Cells[1]),然后找到单元格中的某个隐类型控件(Rows[e.RowIndex]. Cells[1]),但已事先知道该控件是文本框,所以对它进行强制类型转换
,然后获取该文本框的Text属性的值,即用户的输入值。
通过这种方式可以检索到任何的用户的输入值,包括一些不是文本的较特殊的值,如指示复选框是否被选中的bool值,下拉列表框被选中的项的索引等。如果设计者不希望某列能被用户编辑,可以将该列的ReadOnly属性设置为True。
d. RowCancelingEdit事件处理方法的代码大致类似于这样:
说明:由于- 1不是有效索引,将当前编辑行的索引设置为- 1的作用就是使原来处于编辑状态的行退出编辑状态。此时,GridView控件中没有处于编辑状态的行。
③自定义命令的操作
有时需要在GridView的每条记录后添加自定义按钮,对不同的记录数据执行相同的操作,例如,对于图书信息的“加入购物车”操作,对于帖子信息的“审核”操作等。有两种方式可以实现为每条记录后添加自定义按钮:使用按钮列(ButtonField),或在模板列(TemplateField)放入按钮。那么,如何为这些自定义按钮实现操作,下面分模板列和按钮列两种情况进行介绍:
对于模板列,在ItemTemplate项模板放入按钮后,需要在属性面板中设置按钮的CommandName属性,该属性可以通过事件处理方法的参数传递到后台,其作用是为按钮设置一个命令名,以便在后台与其他按钮命令进行区分,如将“加入购物车”按钮的命令名设置为“AddCart”;还需要为按钮的CommandArgument属性绑定某个数据源字段,一般是数据源的主键字段,如将CommandArgument属性绑定到数据源的ISBN书号字段,绑定表达式为:Eval(“bsISBN”)。该属性也能通过事件处理方法的参数传递到后台,这样,在后台编程时就能得到当前记录的主键值,从而对该记录数据进行进一步的操作。
然后,为GridView的RowCommand事件生成事件处理方法,该事件会在用户在GridView中执行任何按钮命令时触发。以加入购物车操作为例,RowCommand事件处理方法的代码类似这样:
对于按钮列,也需要设置它的CommandName属性(注意是列的属性而非按钮的属性)。并为GridView的RowCommand事件生成事件处理方法,同样以加入购物车操作为例,RowCommand事件处理方法的代码类似这样:
与模板列不同的是,按钮列不存在CommandArgument属性,参数e的CommandArgument属性默认被放入了当前行的索引,通过当前行的索引也能获取当前行的其他信息。
【任务实施】
图书管理页面的实现步骤。
①在SQL Server 2005的Manage Studio中,创建网上书店的后台数据库BookStore和图书信息表BookInfo,包含ISBN、书名、作者、出版社、所属类别、单价、封面图片文件名、有无库存8个字段,表结构如图5.12所示。
图5.12图书信息表结构
②新建一个Web页,从“工具箱”的“数据”控件组中,拖放一个GridView控件到页面上,单击工具栏上的“居中对齐”按钮,使控件居中对齐,在属性面板中将该控件的宽度设置为80%。
③绑定数据源:打开Web页的.cs代码文件,创建一个自定义的方法ShowGridData(),功能为:对1)中建立的数据表BookInfo进行查询,将查询结果填充到数据集,并作为GridView的数据源与控件进行数据绑定。该方法能在多处重复使用,代码如下:
然后在Page_Load()事件处理方法调用该方法在页面初始加载时显示数据:
④定制列:选中GridView,在属性面板中将AutoGenerateColumns属性设置为False。单击GridView右上角的“>”智能标记,选择“添加新列”命令,为GridView添加列;或选择“编辑列”命令,在弹出的“字段”编辑对话框中选择某种列类型,单击“添加”按钮,也能为GridView添加列。
注意:有些属性在可视化设置时可能以中文名作为提示,HeaderText属性的中文提示为“页眉文本”,DataField属性的中文名为“数据字段”等,请读者注意属性和中文名的对应关系,如果不能确定,可设置后切换到源视图进行查看。
本任务需要添加如下列。
A.一个BoundField列:用于显示ISBN,HeaderText属性设置为“ISBN”,DataField设置为“bsIsbn”,ReadOnly设置为“True”。
B.一个HyperLinkField列:作用是显示超链接形式的图书名称,单击该超链接,显示封面图片,HeaderText设置为“图书名称”,DataTextField属性设置为“bsBookName”,DataNavigateUrlFields属性设置“bsImageFile”,DataNavigateUrlFormatString属性设置为“~\BookCover\{0}”。
C.一个BoundField列:用于显示图书类别,HeaderText属性设置为“分类”,DataField设置为“bsContentClass”,ReadOnly设置为“True”。
D.一个BoundField列:用于显示作者名,HeaderText属性设置为“作者”,DataField设置为“bsAuthor”,ReadOnly设置为“True”。
E.一个BoundField列:用于显示出版社名,HeaderText属性设置为“出版社”,DataField设置为“bsPublisher”,ReadOnly设置为“True”。
F.一个BoundField列:用于显示图书价格,HeaderText属性设置为“单价”,DataField设置为“bsPrice”,DataFormatString设置为“{0:C}”,将价格信息格式化为保留默认两位小数的货币类型。
G.一个CheckBoxField列:用复选框显示是否库存有货的“是否”两种状态,HeaderText属性设置为“是否有货”,DataField设置为“bsStocked”,该数据源字段必须为bool型。
H.一个CommandField列:用于对某行进行标准流程的删除、编辑、更新以及取消操作,此时最好使用“添加新列”命令的方法而不用“编辑列”命令的方式,在弹出的“添加字段”对话框中,页眉文本对应HeaderText属性,设置为“操作”,按钮类型对应于ButtonType属性,设置为“Link”,并同时选中“删除”和“编辑/更新”复选框。
到此为止,GridView的各列都添加完毕,BoundField列在编辑状态下会自动以文本框的形式显示数据,然而,一旦将该列的ReadOnly属性设置为True,则即使在编辑状态下仍然不能输入,这种方法可以用于控制开放哪些字段以供编辑。从以上的设置可以看出,只有价格信息和是否有货的复选框允许输入和勾选。本任务没有使用模板列,实际上,模板列功能更强,更灵活,使用它,可以实现所有其他列的功能,数据控件中模板的概念和使用方法都非常接近,本项目的第二个任务将以其他控件为载体进行重点介绍。
⑤套用样式方案:单击GridView右上角的“>”智能标记,选择“自动套用格式”命令,打开“自动套用格式”对话框,选择“传统型”样式方案,单击“确定”按钮应用样式方案。
⑥分页:选中GridView,在属性面板中将AllowPaging属性设置为“True”,将PageSize属性设置为“5”,展开PagerSettings属性,将子属性Mode设置为“Numeric”,设置完成后,GridView效果如图5.13所示。
图5.13定制图书信息管理页面的GridView控件
为GridView的PageIndexChanging事件生成事件处理方法,添加分页代码如下:
⑦实现删除、编辑、更新、取消操作:
在ShowGridData()方法的适当位置添加代码,为GridView设置主键,代码如下:
为GridView的RowDeleting、RowEditing、RowUpdating和RowCancelingEdit生成事件处理方法,并添加代码如下:
A.删除操作:
B.编辑操作:
C.更新操作:
D.取消操作:
⑧单击Visual Studio 2008工具栏上的“启动调试”按钮(绿色箭头按钮)或按快捷键“F5”启动调试运行,对代码进行调试后,保证程序能正确运行,效果如图5.14所示。
图书信息管理页面效果图(编辑状态)如图5.15所示。
【拓展与提高】
SQL数据源控件(SqlData Source)
数据源控件用于操作和缓存来自外部(XML文件、数据库等)数据,并作为数据源与数据控件进行数据绑定,使用数据源控件只需进行一些简单的设置就实现之前需要编程才能实现的功能,因此能有效降低开发者的工作量,缩减软件项目的代码总量。
ASP.NET为开发者提供了多种数据源控件,如用于数据库的SqlData Source和Access-DataSource,用于XML文件的XmlDataSource和SiteMapDataSource,用于对象的ObjectData-Source等。这里主要对SqlData Source这种最常用的数据源控件进行介绍,其他的数据源控件的概念和使用方法有类似之处,读者可以使用类比的方式进行自学,另外,本书后面的内容也会对其中的某些数据源控件进行讲解。
图5.14图书信息管理页面效果图(普通状态)
图5.15图书信息管理页面效果图(编辑状态)
SqlData Source是一个内部通过ADO.NET方式连接、操作、缓存关系数据库数据的数据源控件。SqlData Source能自动地打开和关闭数据库,能自动执行事先设置好的SQL语句或存储过程,并能与GridView等数据控件进行数据绑定。SqlData Source还能支持对数据库的插入、更新、删除操作。SqlData Source是UI和数据库之间的桥梁,它能够部分替代之前需要手工完成的ADO.NET代码编写。下面对如何配置和使用SqlData Source进行介绍。
1)建立SqlData Source控件
SqlData Source能够在VS 2005平台的工具箱面板的“数据”控件组中找到,将其添加到Web页面后,会在源视图中自动生成HTML标签:
切换到设计视图,单击SqlData Source控件右上角的“>”智能标记,选择“配置数据源”命令,弹出SqlData Source的数据源配置向导——“选择数据连接”窗口,如图5.16所示。
初次使用时,需要新建连接,单击“新建连接”按钮,弹出“添加连接”对话框,如图5.17所示。
默认外部数据库为SQL Server,单击“更改”按钮可以选择其他类型的外部数据库;在“服务器名”下拉框中输入或选择数据库服务器名称;在“登录到服务器”组框内选择登录验证方式:Windows集成身份验证和SQL Server身份验证,如果使用SQL Server身份验证,还需要输入用户名和密码;在“连接到一个数据库”组框内可以选择要连接的数据库名称,当完成这些设置后,可以单击“测试连接”按钮,测试新建连接是否能成功连接到数据库。
单击“确定”按钮关闭“添加连接”对话框,回到之前的数据源配置向导——“选择数据连接”窗口,会发现新建连接已被添加到下拉框中以供选择。单击“连接字符串”字样前面的“+”,可以看到连接字符串的详细信息。
单击“下一步”按钮进入数据源配置向导——“将连接字符串保存到应用程序配置文件中”窗口,如图5.19所示。
勾选“是,将此连接另存为”复选框,此时会将连接字符串以下面文本框中的名称保存到web.config全局配置文件中。之后如果打开web.config文件,会在“connectionStrings”配置节找到该连接字符串,代码如下:
图5.16 SqlData Source选择连接窗口
图5.17 SqlData Source添加连接
图5.18 SqlData Source查看连接字符串
图5.19 SqlData Source保存连接
单击“下一步”按钮进入数据源配置向导——“配置Select语句”窗口,如图5.20所示。
在此窗口,如果希望为SqlData Source控件自动生成SQL查询语句:点选“指定来自表或视图的列”单选按钮,选择当前数据库中表或视图的名称,然后选中所需要的字段,“*”号表示所有字段,在变灰的“Select语句”文本框中会出现自动生成的SQL查询语句。
如果希望手工编写Select语句或存储过程,可以单击“指定自定义SQL语句或存储过程”单选按钮,并单击“下一步”按钮进入数据源配置向导——“自定义语句和存储过程”窗口,在此可以手工编写SQL语句或选择某个数据库中已创建的存储过程,如图5.21所示。
图5.20 SqlData Source配置查询语句
图5.21 SqlData Source自定义SQL命令
在数据源配置向导——“配置Select语句”窗口,如果需要为查询语句添加条件子句,可以单击“Where”按钮,则弹出“添加where子句”对话框,如图5.22所示。
选择字段名称,选择比较运算符,选择待比较的对象。待比较的对象可以是值、控件、Cookie、Session和QueryString等。需要注意的是,不管待比较的对象是哪种类型,条件子句都会生成一个数据库参数,然后获取待比较对象的值,传递给这个参数。单击“添加”按钮,可以将已经设置好的这一单个条件添加到“WHERE子句”列表。如果WHERE子句包含多个条件,可继续按同样方式设置后再添加。单击“确定”按钮回到之前的数据源配置向导——“配置Select语句”窗口。
如果需要为查询语句排序,可以单击“ORDER BY”按钮,会弹出“添加ORDER BY子句”对话框,如图5.23所示。
图5.22 SqlData Source添加WHERE子句
图5.23 SqlData Source添加ORDER BY子句
选择待排序的字段,并选择升序或降序,此处允许同时选择3个字段作为排序字段,设置完成后,完整的SQL语句会显示在最下面的多行文本框中。单击“确定”按钮,回到之前的数据源配置向导——“配置Select语句”窗口。
单击“高级”按钮,会弹出“高级SQL生成选项”对话框,如图5.24所示。
勾选“生成Insert、Update和Delete语句”复选框,能使SqlData Source控件自动支持对数据的反向增删改操作。单击“确定”按钮,回到之前的数据源配置向导——“配置Select语句”窗口。
当对SQL查询语句的配置完成后,单击“下一步”按钮,进入“测试查询”窗口,单击“测试查询”按钮可以对SQL查询语句的效果进行测试,如果测试结果如预期一样,单击“完成”按钮完成SqlData Source控件的配置,如果与预期不一致,则需单击“后退”按钮退回到前面的向导窗口进行修改,如图5.25所示。
图5.24 SqlData Source生成反向操作命令
图5.25 SqlData Source测试查询
此时,源视图SqlData Source控件HTML标签代码如下:
2)SqlData Source控件的使用
只需进行简单的设置就能够将SqlData Source作为数据控件的数据源进行数据绑定,下面以GridView控件为例进行介绍:
只需单击GridView控件的右上角的“>”智能标记,在出现下拉菜单面板的“选择数据源”下拉框中选择对应的SqlData Source控件的ID即可完成设置,如图5.26所示。
图5.26选择SqlData Source作为数据源
此时,如果选中下拉菜单面板中的“启动分页”“启动编辑”“启动删除”,并且保证SqlData Source控件能自动支持对数据的反向增删改操作,就能在不添加任何代码的情况下,使Grid-View控件实现分页、删除和编辑更新操作,运行效果如图5.27和图5.28所示。
图5.27 SqlData Source作为数据源的图书信息页面运行效果
图5.28 SqlData Source作为数据源的图书信息页面编辑状态
【教学评价】
评价标准见表5.2。
表5.2任务5.1评价标准
续表
任务5. 2 图书信息浏览页面设计
【任务描述】
使用GridView数据控件,可以将批量数据以表格的形式进行显示并同时提供用户交互界面。但并不是所有的批量数据都适合用表格形式显示。例如树型菜单和以列表方式显示的批量数据等,即便所有批量信息都强制以表格形式显示也未免太过单调。
图书信息浏览页面就是以列表形式显示批量数据,列表的每一项(Item)都会显示多个图书信息元素,如ISBN、书名、封面图片、作者、出版社、单价、简介等;同时,列表项也提供交互方式允许用户进行一些相关的操作,如加入购物车操作等。图书信息浏览页面效果如图5.29所示。
图5.29图书信息浏览页面效果图
要实现上图的显示效果,可以使用DataList控件,DataList控件也是一种使用较多的数据控件。与GridView控件相比,它不像GridView控件那样追求功能上面面俱到,而只是保留了数据控件比较精华的、独有的特征,如数据绑定、模板编辑等,从功能和资源消耗(功能越强,资源消耗越大)方面而言,GridView控件如果属于重量级,那么DataList控件应该属于中量级,本教材将在“拓展与提高”部分介绍的Repeater控件则属于轻量级的数据控件。下面首先对DataList控件的特征和使用方法进行介绍。
【知识准备】
(1)数据列表控件(DataList)
DataList以列表形式显示批量数据,列表中的每一项的布局效果和列表其他的布局效果(如标题、页脚、列表项之间的分隔符等)都需要事先使用模板进行定制。同时,DataList也是一种典型的数据控件,也能绑定到实现了IEnumerable接口的任何数据源和ASP.NET数据源控件,也支持自定义操作和对数据库的反向操作。
1)HTML标记
2)主要的属性、方法、事件
说明:DataList的主要属性与GridView的属性有诸多相似之处。
①常用属性。
a.DataSource属性:获取或设置DataList所绑定的数据源对象。
b.DataSourceID属性:获取或设置DataList所绑定的数据源控件的ID。
c.DataKeyField属性:获取或设置与DataList的主键绑定的数据源字段,只能是单个字段。
d.DataKeys属性:获取一个由DataList项的键值构成的集合,一旦为DataList设置了主键,通过该属性获取某项的键值。
e.Items属性:获取由DataList项对象构成的集合。
f.EditItem Index属性:获取或设置DataList中处于编辑状态的项(编辑项)的索引。
g.Selected Item属性:获取DataList中的被选中项(对象)。
h.Selected Index属性:获取或设置DataList中的被选中项的索引。
i.Show Footer属性:获取或设置一个bool值,指示是否显示脚注。
j.ShowHeader属性:获取或设置一个bool值,指示是否显示标题。
k.RepeatColumns属性:获取或设置DataList中显示的项的列数。
l.RepeatDirection属性:获取或设置DataList是按垂直方向显示还是按水平方向显示。
②以下属性指定DataList的模板。
a.Item Template属性:获取或设置DataList中项的模板。
b.A lternatingItem Template属性:获取或设置DataList中交替项的模板。
c.Selected Item Temp late属性:获取或设置DataList中被选中项的模板。
d.EditItem Template属性:获取或设置DataList中编辑项的模板。
e.SeparatorTemplate属性:获取或设置DataList中各项间分隔符的模板。
f.FooterTemplate属性:获取或设置DataList的脚注部分的模板。
g.HeaderTemplate属性:获取或设置DataList的标题部分的模板。
③以下属性用于为DataList设置样式。
a.Item Style属性:指定DataList中项的样式。
b.A lternatingItemStyle属性:指定DataList中交替项的样式。
c.Selected Item Style属性:指定DataList中被选中项的样式。
d.EditItem Style属性:指定DataList中编辑项的样式。
e.SeparatorStyle属性:指定DataList中各项间分隔符的样式。
f.FooterStyle属性:指定DataList中的脚注部分的样式。
g.HeaderStyle属性:指定DataList中的标题部分的样式。
④以下分别为DataList的重要方法和事件。
a.DataBind方法:将数据源与控件相互绑定,绑定后,数据源和控件将同步变化。
b.FindControl方法:在当前的容器控件中搜索指定ID号的子控件。
c.CancelCommand事件:当单击DataList中的命令名为“Cancel”的按钮时触发。
d.DeleteCommand事件:当单击DataList中的命令名为“Delete”的按钮时触发。
e.UpdateCommand事件:当单击DataList中的命令名为“Update”的按钮时触发。
f.EditCommand事件:当单击DataList中的命令名为“Edit”的按钮时触发。
g.ItemCommand事件:当单击DataList中的任何按钮时都会被触发。
h.ItemCreated事件:当在DataList中逐个创建各项时触发。
i.ItemDataBound事件:当DataList的各项逐个进行数据绑定时触发。
3)绑定数据源
要想DataList能正常显示数据,必须为它绑定数据源对象或数据源控件。
绑定数据源对象的方法如下:
向Web页中拖放一个DataList控件到页面布局后的适当位置,设置该控件的ID号,也可以使用默认名称DataList1。
以数据集的数据表或数据视图作为数据源,在后台代码文件中定义成员方法ShowData(),用于进行数据绑定,在ShowData()的末尾添加如下两句代码;或直接在Page_Load事件处理方法末尾添加这两句代码:
说明:将数据集对象ds中的第1个数据表的默认视图作为DataList的数据源,并调用DataBind()方法进行数据绑定。该方法与GridView绑定数据源的方法完全相同。但是,DataList绑定数据源后不会自动生成DataList项,因此,如果直接运行则无法看到效果。
绑定数据源控件的方法如下:
以SqlData Source控件为例,只需点开DataList的“>”智能标记,在出现任务面板的“选择数据源”下拉框中选中需绑定的SqlData Source控件的ID即可。DataList与SqlData Source数据源控件绑定后能够自动生成DataList项,效果如图5.30所示。
效果图显示的是留言本的留言信息,可以看出,数据源的每条记录成为DataList中的1项,每个DataList项显示全部的字段名称和该字段的对应内容,所有信息都以文本方式显示。
进入DataList的模板编辑状态(后面将介绍),可以看到数据字段名称以HTML纯字符显示,对应的字段内容用Label控件显示,该Label控件与数据字段进行过绑定,如图5.31所示。
4)编辑模板
从DataList的模板类属性可以看到,它的可用模板有如下这几种:项模板(ItemTemplate)、交替项模板(AlternatingItemTemplate)、选中项模板(SelectedItemTemplate)、编辑项模板(EditItemTemplate)、分隔符模板(SeparatorTemplate)、标题模板(HeaderTemplate)、脚注模板(FooterTemplate)。
图5.30 DataList绑定SqlData Source原始运行效果
图5.31 DataList绑定SqlData Source后自动生成的项模板
从工具箱的“数据”控件组中拖放一个DataList到页面上,单击该控件右上角的“>”智能标记,会出现DataList的任务面板,可以看出,DataList的任务面板比GridView的在功能上要简单很多,如图5.32所示。
选择“编辑模板”命令,进入模板编辑状态,此时,DataList控件中会显示出当前模板类型和模板编辑区,其任务面板也会出现“结束模板编辑”命令,如图5.33所示。
单击“显示”下拉框的下拉箭头,显示出DataList全部的可用模板类型,如图5.34所示。
图5.32 DataList任务面板(普通状态)
图5.33 DataList任务面板(模板编辑状态)
图5.34 DataList选择模板类型
选定某种模板后,可以在模板编辑区进行DataList项的布局,然后为编辑区中的Web控件进行数据绑定,具体过程与GridView模板列的模板编辑过程相似。
下面用一个实例进行具体说明,该实例为:使用DataList显示留言本的留言信息。
选择ItemTemplate项模板,在模板编辑区放置一个3行3列的表格,合并单元格进行布局调整,在合适位置放入内容(主要是放入Web控件)并调整单元格的对齐方式后,效果如图5.35所示。
图5.35 DataList对项模板布局
说明:图中表格中共放入了4个Label控件,4个Image控件。ID为“Label1”的Label控件用于显示留言人昵称,“Label2”用于显示留言标题,“Label3”用于显示留言内容,“Label4”用于显示留言发布时间;与Label1在同一单元格的Image控件用于动态显示留言人的头像,“人头”“信件”与“企鹅”的Image控件为静态显示,当鼠标移至“信件”或“企鹅”图片上时,会显示出邮箱号和QQ号。
下面以ID为“Label1”的控件为例说明如何将控件属性绑定到数据源字段,单击“Label1”控件的“>”智能标记,选择“编辑DataBindings...”命令,会弹出该控件的绑定对话框,如图5.36所示。
图5.36为DataList中Label控件编写绑定表达式
在左部的“可绑定属性”列表框中选择T e x t属性,在“代码表达式”文本框中输入E v a l("wNickName");单击确定完成绑定。可以看出,DataList的属性和数据字段的绑定与Grid-View的方法完全相同。
其他控件的需绑定属性和绑定表达式见表5. 3,读者可以自己实现。
表5.3留言本实例中需绑定的控件属性和绑定表达式
单击DataList的“>”智能标记,选择“结束模板编辑”命令,退出模板编辑状态。运行该网页,效果如图5.37所示。
对应的HTML代码如下:
图5.37 dataList实例运行效果(留言本)
5)样式定制
DataList控件提供了很多控制样式的属性,这些属性一般还包含很多子级样式属性,使用这些属性可以灵活地对DataList进行外观样式的定制。这些属性一般都能在属性面板中直接设置;同时,DataList还提供了“属性生成器”用于设置这些样式属性:单击DataList的“>”智能标记,选择“属性生成器”命令,弹出DataList的属性生成器对话框,能够对DataList的各种模板进行样式的设置,如图5.38所示。
图5.38 DataList属性生成器
对于一般开发人员而言,为DataList设计出一套美观的样式并不容易。因此,类似于GridView,DataList也提供了多套预设的样式方案供选用:单击DataList右上角的“>”智能标记,选择“自动套用格式”命令,弹出“自动套用格式”对话框,左边“选择架构”列表框中列出了很多预设的样式方案,选中某种样式方案,右边会出现预览效果,单击“应用”按钮会将样式方案应用到当前DataList控件,单击“确定”按钮会应用样式方案并关闭对话框,如图5.39所示。
6)DataList的交互操作
与GridView类似,DataList除了支持数据绑定和模板编辑,也支持用户的交互操作,如对数据库的反向操作,以及自定义命令的操作。但是DataList自身并不支持分页操作,要为DataList实现分页,需要使用另一个称为分页数据源(PagedDataSource)的对象,下面就分别予以介绍:
图5.39 DataList自动套用格式
①对数据库的反向操作
DataList也支持对数据库的反向操作(删、改),但是,相对于GridView,DataList的手工操作更多一些,下面介绍在DataList中如何实现反向操作。
A.进入DataList的模板编辑状态,选择项模板,在项模板编辑区的适当位置添加两个按钮,修改这两个按钮的Text属性为“编辑”“删除”,如图5.40所示。
图5.40为项模板添加编辑、删除按钮
更为重要的是,将“编辑”按钮的CommandName属性设置为“edit”,将“删除”按钮的CommandName属性设置为“delete”,必须这样设置,不能有任何错误,因为DataList会根据CommandName属性识别按钮,并触发对应的事件(在后面的步骤中会介绍)。
B.进入DataList的模板编辑状态,选择编辑项模板,在项模板编辑区的适当位置添加两个按钮,修改这两个按钮的Text属性为“更新”“取消”。而与这两个按钮对应的Command-Name属性必须设置为“update”和“cancel”。编辑项模板中的布局会在DataList进入编辑状态后显示出来,因此对可以进行修改的数据字段,要在编辑项模板中使用文本框进行绑定,如图5.41所示。
可以看到,价格信息换为文本框显示,即是说,在编辑状态下只能对价格进行修改。
C.在DataList控件的属性面板中为EditCommand、UpdateCommand、DeleteCommand和CancelCommand事件生成事件处理方法,这些事件会被具有对应的CommandName命令名的按钮触发。
D.分别为这些事件处理方法添加代码,实现对数据库的反向操作,下面分别进入说明:
a.为事件DeleteCommand的处理方法添加代码,大致如下:
说明:从事件处理方法e中找到待删除项e.Item,并获得待删除项的索引Item Index,通过索引取得该项的键值,以键值为条件,调用ADO.NET实现对数据库的删除操作,删除后,数据库的数据发生改变,调用ShowDataList()方法重新显示数据,这个过程与GridView的删除操作过程相似。
要获取待删除项的键值,则需要在进行数据绑定时为DataList设置主键,即可以将代码添加在ShowDataList()方法末尾,在调用DataBind()方法前,例如,设置ISBN书号字段作为DataList的主键,代码为:,DataList只允许单个数据源字段作为主键,因此代码的形式比GridView的主键设置要简单。
b.为EditCommand的事件处理方法添加代码,大致如下:
说明:用从参数e中取得待编辑项的索引(e. Item. Item Index统一指用户当前操作的项),作为DataList的当前编辑项,即是使该项进入编辑状态。
c.为UpdateCommand事件的处理方法添加代码,大致如下:
图5.41为编辑项模板添加更新、取消按钮
//以主键值作为条件,使用用户的更新值对数据库进行更新,代码省略
…
说明:要获取用户在编辑时的输入值,首先找到当前项e. Item,然后使用项对象的Find-Control()方法按输入控件的ID进行查找,通过FindControl()的返回值获得该输入控件后将其强制类型转换为文本框(也可以是其他输入控件,关键之处已事先知道),然后获取文本框的Text属性值,即可得到用户的输入。
d.为CancelCommand事件的处理方法添加代码,大致如下:
说明:处理方式与GridView相同,将当前编辑项的索引设置为-1就是要使该项退出编辑状态。
②自定义命令的操作
同GridView类似,DataList的每一项也能放入功能按钮,以实现自定义的操作,自定义操作的实现过程如下:
在DataList的项模板编辑区放入按钮,在属性面板中设置按钮的CommandName属性,例如,将“加入购物车”按钮的命令名设置为“AddCart”,为按钮的CommandArgument属性绑定某个数据字段,例如,将CommandArgument属性绑定到ISBN书号字段,绑定表达式为Eval(“bsISBN”)。然后,为DataList的ItemCommand事件生成事件处理方法,该事件会在用户单击DataList中任意按钮时触发。为ItemCommand事件的处理方法添加代码,如果希望为“加入购物车”按钮实现功能,代码大致如下:
由以上代码可以看出,其与GridView的对应代码基本一致。
③分页操作
DataList自身没有内置分页功能,要使DataList能够分页,必须借助另一个类名为Paged-DataSource的对象,该对象的作用是对原始数据源,如数据表、数据视图等,按页进行分流,即只从原始数据源中截取当前页所需的这一部分数据。当该对象作为DataList等数据控件的数据源时,就能保证数据控件只会显示出当前页的数据,这样就间接地实现了分页。
下面首先对PagedDataSource对象用于分页的重要属性进行介绍。
a.AllowPaging属性:设置或获取一个bool值,指示是否允许分页。
b.DataSource属性:指定PagedDataSource对象的原始数据源。
c.PageSize属性:指定PagedDataSource对象的页的大小,即每页包含多少记录。
d.CurrentPageIndex属性:指定PagedDataSource对象中当前页的索引。
e.PageCount属性:获取PagedDataSource对象中总的页数。
f.IsFirstPage属性:获取一个bool值,指示当前页是否是第一页。
g.IsLastPage属性:获取一个bool值,指示当前页是否是最后一页。
下面以一个简单的分页导航界面为例,说明如何在这个分页导航界面规定的操作方式下实现DataList的分页功能,该分页导航界面如图5.42所示。
图5.42 DataList分页导航界面设计
实现步骤:
A.做该分页导航界面,在页面上放入两个超链接按钮和一个标签控件,将默认ID为Link-Button1按钮的Text属性设置为“上一页”,将ID为LinkButton2按钮的Text属性设置为“下一页”。使用标签控件显示第1个数字,默认ID为Label 1,Text设置为“1”,用于显示当前页码;显示第2个数字也使用标签控件,默认ID为Label 2,Text设置为“1”,用于显示总页数。在这种分页导航方式下,因为“上一页”和“下一页”都需要相对于当前页码进行计算,因此,当前页码必须一直保存,不能丢失。由于Web控件在页面提交并刷新后能保持原有状态,因此,用Label控件显示当前页码的同时也是将当前页码保存在Label控件中以备随时取用。
B.设计者需要再为DataList设置数据源,在进行数据绑定时,引入PagedDataSource对象,对原始数据源进行截留。因此,需要在DataList的数据绑定方法ShowDataList()中,添加如下代码:
说明:从代码可以看到,这种方式是对PageDataSource对象进行分页,而不是对DataList进行分页,是在对内存数据进行虚拟分页后,将当前页的数据在页面上显示出来,这是一种新的思考方法,请读者注意理解。
C.为“上一页”和“下一页”按钮生成事件处理方法,并添加代码:
a.“上一页”按钮的事件处理方法如下:
b.“下一页”按钮的事件处理方法如下:
说明,在单击“上一页”或“下一页”按钮时,设计者的主要工作就是计算新的当前页,并回存到页面的Label控件中。因为每次调用ShowDataList()方法都会从页面Label中提取当前页码,重新创建PagedDataSource对象,并重新根据当前页的索引和其他信息进行分页,然后将当前页对应的数据提供给DataList控件。
【任务实施】
图书信息浏览页面的实现。
①仍然使用在任务5.1中建立的数据库BookStore和图书信息表BookInfo,表结构如图5.43所示。
图5.43图书信息表BookInfo的表结构
②新建一个Web页,从“工具箱”的“数据”控件组中,拖放一个DataList控件到页面上,在属性面板中将该控件的宽度设置为100%。
③绑定数据源:打开该Web页对应的.cs代码文件,创建一个自定义的方法ShowListData(),该方法的功能是:对1)中建立的数据表BookInfo进行查询,将查询结果填充到数据集,并作为DataList的数据源与控件进行数据绑定。该方法能在多处重复使用,代码如下:
然后在Page_Load()事件处理方法调用该方法在页面初始加载时显示数据:
④模板编辑:选中DataList控件,单击右上角的“>”智能标记,选择“编辑模板”命令,进入模板编辑模式。在DataList任务面板中选择ItemTemplate项模板,在项模板编辑区,放入一个5行2列的布局表格,将宽度设置为100%,经过一些单元格合并之后,在其中放入1个图片控件,5个标签控件,1个复选框控件,1个按钮控件,加入一些说明文字,并进行一些对齐设置后,效果如图5.44所示。
图5.44图书信息显示页面DataList项模板布局
下面分别对每个控件进行说明。
A.图片控件(Image1):用于显示图书封面图片,绑定的属性是ImageUrl,绑定表达式为:Eval("bsImageFile","~\BookCover\{0}")。
B.标签控件(Label1):用于显示图书名称,绑定的属性是Text,绑定表达式为:Eval("bs-BookName")。
C.标签控件(Label2):用于显示图书的ISBN号,绑定的属性是Text,绑定表达式为:Eval("bsIsbn")。
D.标签控件(Label3):用于显示图书的作者姓名,绑定的属性是Text,绑定表达式为:Eval("bsAuthor")。
E.标签控件(Label4):用于显示出版社名称,绑定的属性是Text,绑定表达式为:Eval("bsPublisher")。
F.标签控件(Label5):用于显示图书价格,绑定的属性是Text,绑定表达式为:Eval("bsPrice","{0:C}")。
G.复选框控件(CheckBox1):用于显示有无库存的状态,绑定的属性是Checked,绑定表达式为Eval("bsStocked")。
H.按钮(Button1):用于执行加入购物车功能,Text属性设置为“加入购物车”,Command-Name属性设置为“AddCart”,绑定的属性是CommandArgument,绑定表达式为Eval("bsIsbn")。
在DataList任务面板中选择AlternatingItemTemplate交替项模板,在交替项模板编辑区,进行与项模板编辑区完全相同的布局设计,只是将布局表格的背景色设置为“#FFCC00”,效果如图5.45所示。
图5.45图书信息显示页面DataList交替项模板布局
对于交替项模板中的各控件,读者很容易找到它在项模板中的对应控件,对这些控件的设置和数据绑定,也和项模板中的对应控件的设置和数据绑定完全相同。对于DataList的其他模板,读者可以自行测试其效果。
⑤实现“加入购物车”命令:为DataList的ItemCommand事件,映射事件处理方法,并添加代码如下:
说明:上述代码在得到需要加入购物车的图书信息的图书ISBN号(主键)后,只是简单的通过消息框的方式将其输出,并没有真正实现加入购物车的功能。真正的实现过程应该是:首先,通过图书的ISBN号获得购物车所需图书的其他信息,如图书名称、价格等,然后在购物车中添加一条图书选购信息,如果此种图书之前已经被选购了,则只需将此种图书的数量增加1,最后跳转到购物车页面,将购物车中的图书选购信息显示出来。在项目4中曾经完成了一个“实现Session购物车”的任务,读者可以去项目4中查看。
⑥实现分页功能:本任务设计的分页导航区包括两个Label控件,ID分别为“lPage”和“lPageCount”,用于显示当前页码和总页数;4个LinkButton按钮,ID分别为“lbPrevious”“lb-Next”“lbFirst”和“lbLast”,用于实现“上一页”“下一页”“首页”和“末页”的分页导航,如图5.46矩形阴影部分所示。
图5.46图书信息显示页面分页导航界面设计
关于为DataList实现分页功能的思路和方法已经在本任务的“知识准备”部分作了详细的介绍,因此,这里只是为保证本任务的实现过程的完整性而将编码过程列出:
A.修改自定义的数据显示方法ShowListData(),代码如下(字体加粗部分是新增的):
B.为4个按钮生成的Click事件的事件处理方法,并添加代码。
a.“上一页”分页导航按钮的事件处理方法如下:
b.“下一页”分页导航按钮的事件处理方法如下:
c.“首页”分页导航按钮的事件处理方法如下:
d.“末页”分页导航按钮的事件处理方法如下:
⑦单击VS 2008工具栏上的“启动调试”按钮(绿色箭头按钮)或按快捷键“F5”启动调试运行,对代码进行调试后,保证程序能正确运行,效果如图5.47所示。
【拓展与提高】
Repeater控件
图5.47图书信息显示页面运行效果图
Repeater控件也是一个能以列表形式显示批量数据的数据控件,它的显示效果和DataList很相近,它的属性、方法、事件与DataList也有很大部分是相同的,它也使用模板并支持数据绑定。前面章节曾经介绍过,Repeater是比DataList量级更轻的控件,这说明Repeater比DataList功能更弱,具体体现为;Repeater相对DataList保留了更少的属性、方法和事件;Repeater相对DataList不支持可视化的模板编辑操作,使用模板需要直接编写HTML页面代码。
1)HTML标记
2)主要属性、方法、事件
①主要属性
a.DataSource属性:获取或设置Repeater所绑定的数据源对象。
b.DataSourceID属性:获取或设置Repeater所绑定的数据源控件的ID。
c.Items属性:获取由Repeater项构成的集合。
d.Item Tem p late属性:指定Repeater的项模板。
e.AlternatingItem Template属性:指定Repeater的交替项模板。
f.SeparatorTem plate属性:指定Repeater的各项间的分隔符模板。
g.FooterTemplate属性:指定Repeater的脚注模板。
h.HeaderTemplate属性:指定Repeater的标题模板。
②主要方法
a.DataBind方法:将数据源与Repeater进行绑定。
b.FindControl方法:在Repeater或其项对象中搜索指定ID号的子控件。
③主要事件
a.ItemCommand事件:当单击Repeater中的任何按钮时都会被触发。
b.ItemCreated事件:当在Repeater中逐个创建各项时触发。
c.ItemDataBound事件:当对Repeater的各项逐个进行数据绑定时触发。
对比DataList分析Repeater的属性、事件和方法,可以发现,由于缺少了支持反向操作的模板和事件,所以Reapter不直接提供对数据库反向操作的支持;由于缺少样式属性,所以Repeater也不支持灵活的定制外观,因此只用于简单显示重复结构信息。
3)使用模板和绑定数据
由于Repeater不支持可视化的模板编辑,因此只能通过手工编写HTML代码的方式使用模板并进行数据绑定,下面使用实例进行说明:
例1使用Repeater显示书名信息,每条书名信息占据一行显示。
实现步骤:
A.从工具箱的“数据”控件组拖放一个Repeater到页面适当位置,采用默认ID。
B.在代码文件的Page_Load事件处理方法中编写代码为Repeater设置数据源,典型代码如下:
当然,也可以使用数据源控件作为数据源,设置方式与DataList完全相同。
C.打开网页文件,切换到源视图,找到Repeater的HTML标签所在的位置,手工编写模板和绑定表达式,完整的HTML代码如下:
上述代码使用Label控件显示图书名称信息,运行效果如图5.48所示。
图5.48 Repeater显示图书名称
4)交互操作
Repeater自身只支持自定义命令按钮的操作,不支持固定操作方式的删除、编辑、更新、取消的数据库反向操作和分页操作。如果要实现数据库反向操作,可能需要使用自定义按钮进行界面和操作设计;如果要实现分页操作,则同DataList一样可以借助PagedDataSource分页数据源对象来实现。这里只介绍自定义命令按钮的实现,下面用一个实例进行说明:
例2对前一个实例进行补充,在每行书名信息后面添加一个“加入购物车”按钮,单击该按钮,弹出消息框显示该图书信息。
实现过程如下:
首先,在页面文件的源视图中对Repeater的HTML代码进行补充,完整代码如下:
上述代码在项模板中增加了一个Button按钮,并将按钮的CommandArgument属性绑定到图书名称字段,运行效果如图5.49所示。
图5.49 Repeater显示自定义按钮
在设计视图中选中Repeater控件,在属性面板事件窗口为ItemCommand事件生成了事件处理方法,切换到源视图,会发现在Repeater标签代码的第1行,自动添加了ItemCommand事件对事件处理器的映射,代码如下:
打开对应的代码文件,在该事件处理方法中添加代码如下:
说明:首先判断按钮的命令名,然后获取传递的命令参数,通过命令参数得到当前项的图书名称(在HTML代码中进行过绑定),然后通过客户端弹出消息框的方式将图书名称显示出来,如图5.50所示。
图5.50 Repeater自定义按钮命令运行效果
【教学评价】
评价标准见表5.4。
表5.4任务5.2评价标准
【归纳总结】
①数据控件也是Web控件的一种。不过,相对于一般的Web控件,它增加了很多的内置功能。其中,模板编辑和属性绑定是数据控件极富特色的功能,这使得一般的Web控件能够作为数据控件的内部元素进行使用。模板和数据绑定的概念在微软新一代的WPF技术中得到了极大的扩展,无疑是微软的最新软件开发技术的核心概念之一。
②数据控件的事件处理机制比较特殊。一般情况下,用户操作的是数据控件内部的子元素或子控件,因此,这些子元素的事件会被首先触发,然后被传导给作为容器的数据控件进行统一处理。那么,如何在数据控件中判断是否有子元素事件被触发,数据控件定义了这样一类事件,当子元素事件被触发时,这类事件也会被触发,如ItemCommand和ItemDataBound就是这样的事件。通过这种机制,数据控件就能实现与用户的交互行为。
③GridView、DataList和Repeater是3个典型的数据控件,它们的使用模式类似,但量级不同:GridView保留了全面功能,资源耗费最大;DataList保留了主要功能,资源耗费中等;Repeater只保留了典型功能,它没有可视化工具的支持,只能完全通过编码进行使用,资源耗费最小。读者不仅应该掌握这些控件的可视化使用方式,还应该掌握它们的编码使用方式,掌握了这3个典型的数据控件的使用,再去学习其他数据控件应该不是一件难事。
【练习与实训】
实训1商品信息包括商品ID,商品名称,商品类型,商品单价,商品图片、商品详细信息、是否有货,使用GridView控件实现商品信息的分页显示、编辑、删除、加入购物车功能,可分别使用数据控件和数据源两种方式实现。
实训2留言信息包括留言ID,留言标题,留言内容,发布人,发布时间,博客名称,博客地址,表情头像、是否会员,使用GridView控件实现留言信息的分页显示、编辑、删除、回复功能,可分别使用数据控件和数据源两种方式实现。
实训3商品信息包括商品ID,商品名称,商品类型,商品单价,商品图片、商品详细信息、是否有货,使用DataList控件实现商品信息的分页显示、编辑、删除、加入购物车功能。
实训4留言信息包括留言ID,留言标题,留言内容,发布人,发布时间,博客名称,博客地址,表情头像、是否会员,使用DataList控件实现留言信息的分页显示、编辑、删除、回复功能。
实训5留言信息包括留言ID,留言标题,留言内容,发布人,发布时间,博客名称,博客地址,表情头像、是否会员,使用Repeater控件实现留言信息的显示和回复功能。