在asp.net 2.0中我们可以像asp.net 1.x一样,有多种编程方式可以访问数据,还可以通过新的数据源控件访问。
这里有多个内置的数据源控件,比如用来访问关系数据库数据的SqlDataSource控件,用来访问类所提供的数据的ObjectDataSoruce控件等等。你还可以创建你自己的自定义数据源控件。
数据源控件作为你的aspx页面和底层数据的代理。为了显示数据源控件查询到的数据,我们要添加其他Web控件到页面上,并且将它和数据源控件绑定。要绑定一个Web控件到一个数据源控件,只需要简单的设置这个Web控件的DataSourceID属性值为数据源控件的ID属性值。
为了获取站点地图中的数据,asp.net提供了SiteMapDataSource控件,它允许我们绑定一个Web控件来显示我们的站点地图。TreeView和Menu这两个Web控件常常用来提供导航用户界面。要绑定站点地图中的数据到这两个控件,添加一个SiteMapDataSource控件到页面中,设置TreeView或者Menu控件的DataSourceID属性值为SiteMapDataSource控件的ID属性值就可以了。举个例子,我们可以用下面这些标记将Menu控件到母板页中:
- < div id="navigation">
- < asp:Menu ID="Menu1" runat="server"
- DataSourceID="SiteMapDataSource1">
- < /asp:Menu>
- < asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" />
- < /div>
为了生成优化的HTML,我们可以绑定SiteMapDataSource控件到Repeater控件,如下:
- < div id="navigation">
- < ul>
- < li>< asp:HyperLink runat="server" ID="lnkHome"
- NavigateUrl="~/Default.aspx">Home< /asp:HyperLink>< /li>
- < asp:Repeater runat="server" ID="menu"
- DataSourceID="SiteMapDataSource1">
- < ItemTemplate>
- < li>
- < asp:HyperLink runat="server"
- NavigateUrl="< %# Eval("Url") %>">
- < %# Eval("Title") %>
- < /asp:HyperLink>
- < /li>
- < /ItemTemplate>
- < /asp:Repeater>
- < /ul>
- < asp:SiteMapDataSource ID="SiteMapDataSource1"
- runat="server" ShowStartingNode="false" />
- < /div>
SiteMapDataSource控件每次返回站点地图层次中的一级,从站点地图中的根节点开始(在我们的站点地图中是Home),然后是下一个级(Basic Reporting,Filtering Reports和Customized Formatting)等等。
当将SiteMapDataSource绑定到Repeater时,它遍历***级并且用ItemTemplate显示***级的每个SiteMapNode实例。我们可以使用Eval(属性名称)访问SiteMapNode的细节,这样我们就可以得到SiteMapNode的Url和Title属性给HyperLink控件。
下面显示的是上面使用Repeater控件例子生成的HTML标记:
- < li>
- < a href="/Code/BasicReporting/Default.aspx">Basic Reporting< /a>
- < /li>
- < li>
- < a href="/Code/Filtering/Default.aspx">Filtering Reports< /a>
- < /li>
- < li>
- < a href="/Code/CustomFormatting/Default.aspx">
- Customized Formatting< /a>
- < /li>
从上面可以看出,站点地图的第二级节点(Basic Reporting,Filtering Reports和Customized Formatting)被显示而不是***个。
这是因为SiteMapDataSource控件的ShowStartingNode属性被设为false,导致SiteMapDataSource跳过了站点地图的根节点取而代之的是从站点地图的层次的第二级开始返回信息。
为了显示Basic Reporting,Filtering Reports和Customized Formatting的子SiteMapNode,我们可以向先前的Repeater的ItemTemplate里添加另外一个Repeater。第二个Repeater将绑定到SiteMapNode实例的子结点属性,如下:
- < asp:Repeater runat="server" ID="menu" DataSourceID="SiteMapDataSource1">
- < ItemTemplate>
- < li>
- < asp:HyperLink runat="server"
- NavigateUrl="< %# Eval("Url") %>">
- < %# Eval("Title") %>< /asp:HyperLink>
- < asp:Repeater runat="server"
- DataSource="< %# ((SiteMapNode)
- Container.DataItem).ChildNodes %>">
- < HeaderTemplate>
- < ul>
- < /HeaderTemplate>
- < ItemTemplate>
- < li>
- < asp:HyperLink runat="server"
- NavigateUrl="< %# Eval("Url") %>">
- < %# Eval("Title") %>< /asp:HyperLink>
- < /li>
- < /ItemTemplate>
- < FooterTemplate>
- < /ul>
- < /FooterTemplate>
- < /asp:Repeater>
- < /li>
- < /ItemTemplate>
- < /asp:Repeater>
这两个Repeater生成的HTML标记(为了节省篇幅一些标记被移除了):
- < li>
- < a href="/Code/BasicReporting/Default.aspx">Basic Reporting< /a>
- < ul>
- < li>
- < a href="/Code/BasicReporting/SimpleDisplay.aspx">
- Simple Display< /a>
- < /li>
- < li>
- < a href="/Code/BasicReporting/DeclarativeParams.aspx">
- Declarative Parameters< /a>
- < /li>
- < li>
- < a href="/Code/BasicReporting/ProgrammaticParams.aspx">
- Setting Parameter Values< /a>
- < /li>
- < /ul>
- < /li>
- < li>
- < a href="/Code/Filtering/Default.aspx">Filtering Reports< /a>
- < /li>
- < li>
- < a href="/Code/CustomFormatting/Default.aspx">
- Customized Formatting< /a>
- < /li>
使用的CSS风格选择自Rachel Andrew的书:The CSS Anthology: 101 Essential Tips, Tricks, & Hacks,< ul>和< li>元素的风格将显示如下:
图11:用两个Repeater和一些CSS显示的菜单
这个菜单在母板页中定义的,绑定了在Web.sitemap中定义的站点地图,这意味着所有站点地图的修改会立即反应到所有使用了Site.master母板页的页面。
关掉视图状态
所有的asp.net控件可以随意的保持它们的状态到View State(译注:当原文中采用的是开头字母大写的ViewState将不翻译)中,最终生成HTML时它被系列化并保存在一个隐藏的表单域中。控件用ViewState来记忆它们在页面返回时被程序改变的状态,比如Web控件绑定的数据。如果视图状态允许信息可以在页面返回时保持,它会增大发送到客户端HTML代码的尺寸,如果在没有确切的监控下会使页面膨胀得很厉害。数据显示控件-尤其是GridView控件-会显著地增加大量的额外的标记到页面中。当然,这些增长可能对宽带用户毫无影响,但是视图状态会给拨号上网的用户增加几秒钟的延迟。
要观察视图状态的影响,在浏览器里打开这个页面然后查看页面的源代码(对于Internet Explorer,点击”查看”菜单并且选择源代码选项)。你还可以打开页面跟踪选项以观察这个页面上每个控件的视图状态。视图状态的信息被系列化并放在位于跟随在< form>标签后面的< div>元素里的名为_VIEWSTATE的隐藏表单域中。
视图状态只在页面上使用了Form时才会被保持;如果你的aspx页面没有包含
< form runat=”server”>的声明,那么***产生的HTML标记中将不含有VIEWSTATE隐藏表单域。
母板页产生的VIEWSTATE隐藏表单域大概有1800个字节。这些额外的数据主要是SiteMapDataSource控件为Repeater控件提供的数据内容产生的。也许1800字节左右看起来还不算很多,但是使用了GridView并且使用了很多字段和记录的视图状态很容易就膨胀10倍或更多。
可以将EnableViewState属性设为false在页面级或者控件级关闭视图状态,从而可以减少产生的标记的大小。Web控件利用视图状态在页面返回时保持要绑定到数据显示控件的数据,当关闭了数据显示控件的视图状态后,在每次页面返回时都必须重新绑定数据到控件。在asp.net 1.x的时候这个职责落到开发者身上;在asp.net 2.0里,页面返回时,数据显示控件会在必要的时候重新绑定数据。
设置Repeater控件的EnableViewState为false可以减少页面的视图状态。可以通过属性窗口设置或者在代码视图里手动修改。通过这些改变,Repeater标记将会像这样:
- < asp:Repeater runat="server" ID="menu" DataSourceID="SiteMapDataSource1"
- EnableViewState="False">
- < ItemTemplate>
- < i>ItemTemplate contents omitted for brevity< /i>
- < /ItemTemplate>
- < /asp:Repeater>
经过这些变化,页面产生的视图状态减少到52个字节,减少了97%的视图状态数据!在这个指南系列里我会关闭所有数据控件的视图状态以减少产生标记的大小。在大多数例子里会在没有提示的情况下将EnableViewState属性设为false。
仅有当数据Web控件必须打开它的视图状态才能提供期望的功能的情况下我们才讨论。
【编辑推荐】