在ASP.NET 2.0中操作数据之四:使用ObjectDataSource展现数据

  在完成了应用程序架构和页面的设计后,我们可以开始探讨如何实现多种多样的普通数据到报表展现的任务。前面我们已经了解到如何在从数据访问层和业务逻辑层绑定数据到ASP.NET页面上的数据控件。在ASP.NET 1.x应用程序中,通过对数据控件的DataSource属性赋值然后调用控件的DataBind()方法从而实现数据展现的方式在ASP.NET 2.0应用程序中可以继续使用。然而,ASP.NET 2.0的数据源控件提供了一种新的方式,使用这些控件可以让你轻松从上文中创建的业务逻辑层中进行数据绑定,甚至不需要手写一行的代码。

  ASP.NET 2.0提供了五种内置的数据源控件:SqlDataSource、AccessDataSource,、ObjectDataSource、XmlDataSource、和SiteMapDataSource,尽管如果有需要的话你还可以构建自己的自定义数据源控件(custom data source controls)。既然我们在前文中已经完成了应用程序示例的系统架构,基于已有的业务逻辑类我们将使用ObjectDataSource。

图1: ASP.NET 2.0包括五种内置的数据源控件

  ObjectDataSource充当别的对象的代理。通过配置ObjectDataSource,我们指定这些底层的对象,还有这些对象的方法如何映射到ObjectDataSource的Select、Insert、Update和Delete方法。一旦底层的对象被指定并且其方法映射到ObjectDataSource的方法后,我们就可以把ObjectDataSource绑定到页面上的Data Web 服务器控件。ASP.NET提供了许多Data Web 服务器控件,包括GridView、DetailsView、RadioButtonList和DropDownList等等。在页面的生命周期中,Data Web 服务器控件可能需要访问它所绑定的数据,这将通过调用ObjectDataSource的Select方法来实现;如果这个Data Web 服务器控件还支持插入、更新或者删除,那么将调用ObjectDataSource的Insert、Update或者Delete方法。这些调用会通过ObjectDataSource被发送到适当的底层对象的方法,如下图所示。

图2:ObjectDataSource充当一个代理

  虽然ObjectDataSource被用来实现插入、更新或者删除数据,但暂时我们只集中讨论返回数据,以后的章节再探讨使用ObjectDataSource和Data Web 服务器控件实现数据修改。

第一步:添加和配置ObjectDataSource控件

  首先,打开BasicReporting文件夹中的SimpleDisplay.aspx页面,切换到设计视图,从工具箱拖拽一个ObjectDataSource控件到页面。它在设计界面显示为一个灰色的方块,这是因为它不产生任何的声明标记;它仅仅是通过调用制定的对象的方法存取数据。通过ObjectDataSource返回的数据可以展现到Data Web 服务器控件,例如GridView、DetailsView、FormView等等。

  注意:作为另一种选择,你也可以先在页面上添加一个Data Web 服务器控件,然后“显示智能标记”,从“选择数据源”下拉框中选择〈新建数据源…〉进入数据源配置向导来添加一个ObjectDataSource。

  为了指定ObjectDataSource的底层对象并且把该对象的方法映射到ObjectDataSource的的方法,可以点击ObjectDataSource的智能标记中的“配置数据源”链接进入数据源配置向导。

图3: 点击智能标记中的“配置数据源”链接

  这将进入数据源配置向导。首先,我们需要给ObjectDataSource指定一个业务对象。如果勾选上“只显示数据组件”,那么下拉框中就仅仅显示出那些以[DataObject]特征修饰过的对象。当前这个列表中应该包含了类型化数据集中表适配器对象(TableAdapters)和前文中我们已经创建的业务对象。如果你忘了给业务逻辑类增加[DataObject]特征,那么当前列表中讲看不到它们。如果是那样的话,你也可以不勾选“只显示数据组件”从而看见所有对象,这就可以把业务对象包含进来(连同类型化数据集中的其他类 –DataTables、 DataRows等等)

  在第一屏中从下拉列表中选择业务对象ProductsBLL ,然后点击“下一步”。

图4: 指定ObjectDataSource 控件使用的业务对象

  在下一屏中向导中你可以选择ObjectDataSource要调用的方法。下拉列表中方法是从上一屏中选定的业务对象获得的。这里我们可以看到GetProductsByProductID,GetProducts,GetProductsByCategoryID和GetProductsBySupplierID这几个方法。从下拉列表中选择方法GetProducts然后点击“完成”(如果你已经像前文展示那样给ProductBLL的方法增加了[DataObjectMethod]特征,那么该项会被默认选中)。

图5: 从“Select”Tab页选择返回数据的方法

  手工配置ObjectDataSource

ObjectDataSource配置向导提供了一个快捷的方式来指定它使用的对象并关联需要调用的方法。不过,你也可以通过它的属性来配置ObjectDataSource,不管是通过属性窗口还是直接在声明标记里。只需简单地将TypeName属性设置为使用的业务对象的名称,将SelectMethod属性设置为提取数据时需要调用的方法名称。

 <asp:ObjectDataSource ID="ObjectDataSource1" runat="server"

  SelectMethod="GetProducts"

  TypeName="ProductsBLL">

</asp:ObjectDataSource>

  尽管你可能更喜欢数据源配置向导,但有时你还是需要手工配置ObjectDataSource,因为配置向导只列出已经开发的类。如果你希望把ObjectDataSource绑定到.NET Framework里的类–例如 Membership class来存取登陆用户信息,或者Directory class 来管理文件系统信息,那么你就需要手工设置ObjectDataSource的属性。

第二步:添加一个Data Web服务器控件并将它绑定到ObjectDataSource

  在ObjectDataSource添加到页面并完成配置之后,我们就可以添加一个Data Web服务器控件到页面来展现通过ObjectDataSource的Select方法返回的数据。所有的Data Web服务器控件都可以绑定到ObjectDataSource;下面我们看看如何将ObjectDataSource的数据展现到GridView、DetailsView、和 FormView 。

绑定一个GridView到ObjectDataSource

  从工具箱添加一个GridView控件到页面SimpleDisplay.aspx的设计界面。从GridView的智能标记,选择我们在第一步中添加的ObjectDataSource控件作为数据源。这将根据ObjectDataSource的Select方法所返回数据的每一个属性(即类型化数据集Products所定义的属性)自动地在GridView控件里产生一个绑定列(BoundField)。

图6: 添加一个GridView控件到页面并绑定到ObjectDataSource

图7: 通过编辑列对话框管理GridView控件的绑定列

花一些时间修改GridView控件的绑定列,移除ProductID, SupplierID, CategoryID, QuantityPerUnit, UnitsInStock, UnitsOnOrder, 和 ReorderLevel这几列。操作很简单,从左下方的列表中选中这些列然后点击删除按钮(红色交叉)就可以移除它们。然后,重新排列一下,选中CategoryName 和 SupplierName两个绑定列并点击向上箭头按钮,使它们排放在UnitPrice列之前。分别设置Products、Category、Supplier和 Price这几个剩下的绑定列的HeaderText属性。然后,格式化Price列为货币–设置该绑定列的HtmlEncode属性为False并且设置DataFormatString属性为{0:c} 。最后,通过ItemStyle/HorizontalAlign属性设置绑定列Price的水平靠右对齐以及CheckBox列Discontinued水平居中显示。

 <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" EnableViewState="False">

 <Columns>

  <asp:BoundField DataField="ProductName" HeaderText="Product" SortExpression="ProductName" />

  <asp:BoundField DataField="CategoryName" HeaderText="Category" ReadOnly="True" SortExpression="CategoryName" />

  <asp:BoundField DataField="SupplierName" HeaderText="Supplier" ReadOnly="True" SortExpression="SupplierName" />

  <asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}" HeaderText="Price"

   HtmlEncode="False" SortExpression="UnitPrice">

   <ItemStyle HorizontalAlign="Right" />

  </asp:BoundField>

  <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued" SortExpression="Discontinued">

   <ItemStyle HorizontalAlign="Center" />

  </asp:CheckBoxField>

 </Columns>

</asp:GridView>

图 8: GridView控件的绑定列定制完成

使用主题(Themes)保持显示风格的一致

  这里会尽可能地移除控件层面的样式设置,取而代之的是使用在一个外部文件里定义的级联样式表。文件Styles.css包含了DataWebControlStyle、HeaderStyle、RowStyle和 AlternatingRowStyle 这几种CSS样式可以用来指示Data Web服务器控件的外观。为了实现这一点,我们可以设置GridView控件的CssClass属性为DataWebControlStyle,HeaderStyle、RowStyle和 AlternatingRowStyle的CssClass属性也类似地设置。

  如果我们设置了这些CssClass属性到Web控件,那么我们不得不记得明确地把每一个属性的值和每一个Data Web服务器控件记录到我们的手册中。一种更为方便管理的方法是使用一个Theme定义CSS样式跟GridView、 DetailsView和FormView控件的属性之间的关联关系。Theme是一个控件层面的属性设置、图片和CSS样式的集合,它可以应用到整个站点的所有页面强制约束外貌和感观。

  我们的Theme将不会包含图片和CSS文件(我们会把stylesheet Styles.css文件照旧留在web应用程序的根目录下),但是它会包含两个外观(Skin)。外观是一个包含Web控件的默认属性设置的文件。特别地,我们将创建一个Skin文件为GridView和 DetailsView定义外观,标示默认的CssClass关联的属性。

  在解决方案资源管理器里选中当前项目,从右键菜单中选择“添加新项”,添加一个外观文件到你的项目并命名为GridView.skin 。

图9: 添加一个外观文件并命名为GridView.skin

  Skin files need to be placed in a Theme, which are located in the App_Themes folder. Since we don't yet have such a folder, Visual Studio will kindly offer to create one for us when adding our first Skin. Click Yes to create the App_Theme folder and place the new GridView.skin file there.

  外观文件需要被放置到一个主题里,而主题文件则存放在App_Themes文件夹里。因为我们目前还没有这个文件夹,当我们添加第一个外观文件时,Visual Studio会友善地提议为我们创建一个。点击“是”,自动创建App_Theme文件夹并把刚刚添加的GridView.skin文件放置在那里。

图 10: 让Visual Studio自动创建App_Theme文件夹

这将在App_Themes文件夹中自动创建一个主题,主题名称为GridView并包含了外观文件GridView.skin 。

图 11: 主题GridView已被添加到 App_Theme 文件夹

  把主题GridView重命名为DataWebControls(从GridView文件夹右键菜单中选择重命名)。然后,进入下面所见的GridView.skin文件的标记:

<asp:GridView runat="server" CssClass="DataWebControlStyle">

 <AlternatingRowStyle CssClass="AlternatingRowStyle" />

 <RowStyle CssClass="RowStyle" />

 <HeaderStyle CssClass="HeaderStyle" /> 

</asp:GridView>

  使用了主题DataWebControls后,这将定义任何一个页面中任何一个GridView控件与CssClass相关属性的默认值。让我们添加一个另一个针对DetailsView控件的外观,这个控件我们不久就会用到。在主题DataWebControls添加一个命名为DetailsView.skin的外观,并加入如下的标记:

<asp:DetailsView runat="server" CssClass="DataWebControlStyle">

 <AlternatingRowStyle CssClass="AlternatingRowStyle" />

 <RowStyle CssClass="RowStyle" />

 <FieldHeaderStyle CssClass="HeaderStyle" />

</asp:DetailsView>

  关于我们的主题设置,最后一部就是将主题应用到我们的ASP.NET页面。一个主题可以一页一页地应用到页面,也可以应用到一个站点下的所有页面。让我们把主题应用到站点下的所有页面。为了实现这一点,在Web.config的<system.web>片断里加入下面的标记:

<pages styleSheetTheme="DataWebControls" />

  这就顺利完成了!在主题样式表里预设的属性将不会覆盖直接在控件层面设定的属性。如果希望主题里的设置高于控件的设置,则需要在主题样式表里使用主题特征;然而不幸地,主题特征的设置并不出现在Visual Studio 的逻辑视图。查阅 ASP.NET Themes and Skins Overview 和 Server-Side Styles Using Themes 获取更多的关于主题和外观的信息; 查看 How To: Apply ASP.NET Themes 获得更多的关于如何配置页面去使用一个主题的信息。

图 12: The GridView显示 Product's Name, Category, Supplier, Price, and Discontinued Information

在 DetailsView控件里每次显示一条数据

  在GridView控件里,从绑定的数据源控件返回的数据每条记录会被显示为一行。然而有时候,我们仅仅需要显示一条单独的记录,或者每次只显示一条记录。DetailsView控件提供了这个功能,它表现为一个两列的HTML的<table>,每一行显示一个字段或者一个属性。你可以想象DetailsView是只有一条数据的GridView翻转90度。

  首先,在页面SimpleDisplay.aspx里GridView控件的上方添加一个DetailsView控件。然后,把它绑定到GridView的同一个ObjectDataSourc控件。正如GridView控件那样,它会根据ObjectDataSource的Select方法所返回的数据,每一个属性生成一个绑定列。唯一不同的是,DetailsView的绑定列是水平排列的。

图 13: 添加一个DetailsView 控件到页面并绑定到ObjectDataSource

类似GridView,DetailsView的绑定列也可以调整提供一些用户化的展现。图14展示了DetailsView控件在设置好绑定列和CssClass属性后使它的外观类似于GridView的例子。

图 14: DetailsView 控件显示一条记录

注意DetailsView控件只显示它的数据源里的第一条记录。为了让用户可以浏览所有记录,我们必须允许DetailsView分页。为了实现这个,回到Visual Studio,在DetailsView的智能标记中勾选上“启用分页”。

图 15: 允许DetailsView 控件分页

图 16: 启用分页后,DetailsView控件允许用户查看任何一个Products

以后的教程中中我们将详细讨论关于分页。

一种更灵活的排版用作每次显示一条记录

  使用DetailView展现ObjectDataSource返回的每一条数据显得有些呆板。我们可能会需要更灵活的数据展现方式。例如,在每一个单独的行里,在显示product's name, category, supplier, price, 和 discontinued information这些信息的基础上,我们可能需要product name 和 price两列显示<h4>的列头,而category 和 supplier则以较小的字体显示在name和price下方。另外,我们也许不太在意属性名(Product, Category,等等)显示在属性值后面。

  FormView控件提供了这个层面的用户化定制。在使用字段的基础上(像GridView 和 DetailsView那样),FormView控件使用模版,这可以让我们混合使用Web服务器控件,静态的HTML和绑定语法(databinding syntax)。如果你熟悉ASP.NET 1.x中的Repeater控件,你可以认为FormView是只显示一条记录的Repeater 。

  在页面SimpleDisplay.aspx的设计界面添加一个FormView控件。一开始FromView控件显示为一个灰色的方块,并告知我们需要编辑模版内容,需要使用ItemTemplate 。

图 17: FormView必须包含一个ItemTemplate

  你可以通过FormView的智能标记直接给它绑定一个数据源控件,这将自动创建一个默认的ItemTemplate(如果ObjectDataSource设置了InsertMethod 和 UpdateMethod,那么同时也会自动创建EditItemTemplate 和 InsertItemTemplate)。不过,这里的示例我们将手工绑定FormView并设置其ItemTemplate 。首先,设置FormView的DataSourceID属性为ObjectDataSource的ID: ObjectDataSource1,然后,创建ItemTemplate,在一个<h4>里显示product's name 和 price,category 和 supplier则以较小的字体显示在下方。

 <asp:FormView ID="FormView1" runat="server" DataSourceID="ObjectDataSource1" EnableViewState="False">

 <ItemTemplate>

  <h4><%# Eval("ProductName") %> (<%# Eval("UnitPrice", "{0:c}") %>)</h4>

  Category: <%# Eval("CategoryName") %>; Supplier: <%# Eval("SupplierName") %>

 </ItemTemplate>

</asp:FormView>

图 18: 第一个产品 (Chai) 显示为预定的格式

<%# Eval(propertyName) %>是绑定语法。方法Eval返回绑定到FormView的对象的指定属性的值。查阅Alex Homer的文章Simplified and Extended Data Binding Syntax in ASP.NET 2.0获取更多的关于数据绑定的细节。

  跟DetailsView一样,FormView置显示ObjectDataSource返回的第一条记录。你可以启用FormView的分页功能,从而让访问者可以依次查看每个产品。

总结

  有赖于ASP.NET 2.0的ObjectDataSource控件,我们可以方便地完成从业务逻辑层获取和展现数据而不需要写一行代码。OjbectDataSource调用指定的类的方法并且返回结果。这些结果可以展现在绑定了ObjectDataSource的Data Web服务器控件。本章节我们看了如何绑定到GridView、DetailsView、和FormView 控件到ObjectDataSource 。

  到目前为止我们仅仅看了如何使用OjbectDataSource调用一个没有参数的方法,但如果我们想调用一个需要传入多个参数的方法,例如类ProductBLL里的GetProductsByCategoryID(categoryID)方法呢?为了调用需要传入一个或多个参数的方法,我们需要配置ObjectDataSource指定这些参数的值。在下一章中我们来看看如何实现。

祝编程快乐!

作者简介

Scott Mitchell,著有六本ASP/ASP.NET方面的书,是4GuysFromRolla.com的创始人,自1998年以来一直应用微软Web技术。Scott是个独立的技 术咨询顾问,培训师,作家,最近完成了将由Sams出版社出版的新作,24小时内精通ASP.NET 2.0。他的联系电邮为mitchell@4guysfromrolla.com,也可以通过他的博客http://ScottOnWriting.NET与他联系。

(0)

相关推荐

  • 在ASP.NET 2.0中操作数据之三:创建母版页和站点导航

    导言 通常,用户友好的个性化站点都有着一致的,站点统一的页面布局和导航体系.Asp.net 2.0引入的两个新特性给我们在统一站点的页面布局和站点导航上提供了简单而有效的工具,它们是母板页和站点导航.母板页允许开发者创建统一的站点模板和指定的可编辑区域.这样,aspx页面只需要给模板页中指定的可编辑区域提供填充内容就可以了,所有在母板页中定义的其他标记将出现在所有使用了该母板页的aspx页面中.这种模式允许开发者可以统一的管理和定义站点的页面布局,因此可以容易的得到拥有统一的视觉和感觉的页面并且

  • ASP.NET 2.0中的数据操作之九:跨页面的主/从报表

    导言 在前面的两篇教程中,我们看到了如何在单一页面中显示主/从报表, 它使用DropDownList显示主记录,使用GridView或DetailsView显示详细信息. 另外一种常见的主/从报表模式是在一个页面中显示主记录而在另一个页面中显示详细信息.互联网上的论坛,如www.asp.net ,就是该模式在实际应用中非常典型例子. Asp.Net论坛由多个子论坛组成: Getting Started, Web Forms, Data Presentation Controls 等等. 每个子论

  • 在ASP.NET 2.0中操作数据之六:编程设置ObjectDataSource的参数值

    导言 正如我们在上一节的教程中所看到的,有很多可供选择的方式把参数的值传递到OjbectDataSource的方法里.假如参数值是采用硬编码方式,来源于页面上的一个Web控件,又或者其他可被数据源Parameter对象读取的源,那么这个值可以绑定到输入参数而不需要写一行的代码. 然而有些时候,参数值来自某些在数据源的内置Parameter对象里还没有计算出来的源.假如我们的站点支持我们的考虑那么我们也许希望参数基于当前登录用户.又或者我们在参数传送到ObjectDataSource的隐含对象的方

  • [翻译]Scott Mitchell 的ASP.NET 2.0数据教程

    Scott Mitchell 的ASP.NET 2.0数据教程目录索引 01.创建一个数据访问 02.创建一个业务逻辑层 03.母板页和站点导航 04.使用ObjectDataSource展现数据 05.声明参数 06.编程设置ObjectDataSource的参数值 07.使用DropDownList过滤的主/从报表 08.使用两个DropDownList过滤的主/从报表 09.跨页面的主/从报表 10.使用 GridView和DetailView实现的主/从报表 11.基于数据的自定义格式化

  • 在ASP.NET 2.0中操作数据之五:声明参数

    导言 在上一章的教程中,我们看了GridView.DetailsView和FormView绑定到OjbectDataSource控件显示数据,ObjectDataSource调用了类ProductsBLL的GetProducts()方法.方法GetProducts()返回一个有Northwind数据库的Products表的所有记录组成的强类型数据表.类ProductsBLL还包含了其它返回部分数据的方法:GetProductByProductID(productID),GetProductsBy

  • 在ASP.NET 2.0中操作数据之一:创建一个数据访问层

    导言 作为web开发人员,我们的生活围绕着数据操作.我们建立数据库来存储数据,写编码来访问和修改数据,设计网页来采集和汇总数据.本文是研究在ASP.NET 2.0中实现这些常见的数据访问模式之技术的长篇系列教程的第一篇.我们将从创建一个软件框架开始,这个框架的组成部分包括一个使用强类型的DataSet的数据访问层(DAL),一个实施用户定义的业务规则的业务逻辑层(BLL),以及一个由共享页面布局的ASP.NET网页组成的表现层.在打下这个后端的基础工作之后,我们将开始转向报表,示范如何显示,汇总

  • ASP.NET 2.0中的数据操作之七:使用DropDownList过滤的主/从报表

    导言 主/从报表是一种很常见的报表, 这类报表中首先会显示一些主记录. 然后用户可以深入(追溯)某条主记录来查看该主记录的详情. 主/从报表是显示一对多关系的理想选择, 比如一个报表显示所有的产品类别,然后根据用户选择的特定类别显示与之关联的产品. 另外, 主/从表在显示"宽"表(有很多列的表)的详细信息时也很有用.例如主/从报表的主表部分显示数据库中产品表的产品名称和单价, 具体到某一个产品时再显示其他的产品字段(类别,供应商,单位数量,等等). 有很多方法可以实现主/从报表. 在这

  • 在ASP.NET 2.0中操作数据之十:使用 GridView和DetailView实现的主/从报表

    导言 在前面的教程我们看到了如何使用两个页面(一个主页,用于列出供应商; 一个明细页,用于显示选定供应商提供的产品)创建主/从报表 . 这种两个页面的报表格式也可以集中在一个页面上. 这篇教程将会使用一个GridView, 它的每一行都包含产品的名称和单价以及一个选择按钮. 单击一个产品的选择按钮会在同一页的DetailsView控件上显示该产品的全部详细信息. 图 1: 单击选择按钮显示产品明细 Step 1: 创建一个可选择行的GridView 回想一下前面的跨页的主/从报表, 它的每个主记

  • 在ASP.NET 2.0中操作数据之二:创建一个业务逻辑层

    导言 本教程的第一节所描述的数据访问层(Data Access Layer,以下简称为DAL)已经清晰地将表示逻辑与数据访问逻辑区分开了.不过,即使DAL将数据访问的细节从表示层中分离出来了,可它却不能处理任何的业务规则.比如说,我们可能不希望产品表中那些被标记为"停用"的产品的"分类编号"或"供应商编号"被更新:我们还可能需要应用一些资历规则,比如说我们都不希望被比自己的资历还要浅的人管理.另外一个比较常见的情况就是授权,比如说只有那些具有特殊

  • ASP.NET 2.0中的数据操作之八:使用两个DropDownList过滤的主/从报表

    导言 在前面的指南中我们研究了如何显示一个简单的主/从报表, 该报表使用DropDownList和GridView控件, DropDownList填充类别,GridView显示选定类别的产品. 这类报表用于显示具有一对多关系的记录时非常合适, 同时它也可以很容易的被扩展以显示多个一对多关系的数据. 比如, 一个订单系统应该包含表示客户,订单和订单明细的表. 一个客户也许有多个订单,每个订单又包含多条订单项. 这样的数据可以使用两个DropDownList和一个GridView呈现给用户. 第一个

随机推荐