21.3 创建简单的Web部件页面
前面已经阐述过,Web部件技术可以很好地解决用户的个性化服务需求,从而使网站用户体验度大大提高。在本节,就通过一个简单的示例程序来讨论一下如何创建Web部件页面以及Web部件的生命周期。
21.3.1 Web部件的使用方法
谈到对Web部件的使用,通常,可以通过如下三种方法之一来使用Web部件:
1)页开发。页开发是指开发人员可以使用可视化设计工具Microsoft Visual Studio 2010来创建使用Web部件的页。与其他ASP.NET标准控件的使用方法一样,同样可以在Visual Studio可视化设计器中使用拖放的方式来创建及配置Web部件控件的功能。例如,可以使用该设计器将一个Web部件区域或一个Web部件编辑器控件拖到设计图面上,然后使用Web部件控件集所提供的用户界面将该控件配置在设计器中的正确位置,从而可以加快Web部件应用程序的开发速度并减少必须编写的代码量。
2)控件开发。可以将现有的任意ASP.NET控件用做Web部件控件,包括标准的Web服务器控件、自定义服务器控件和用户控件。若要通过编程最大限度地控制环境,还可以创建从WebPart类派生的自定义Web部件控件。在开发单个Web部件控件时,通常会创建一个用户控件并将其用做Web部件控件,或者开发一个自定义Web部件控件。
作为一个开发自定义Web部件控件的示例,可以创建一个控件以提供其他ASP.NET服务器控件所提供的任何功能,这可能对打包为可个性化设置的Web部件控件十分有用,这样的控件包括日历、列表、财务信息、新闻、计算器、用于更新内容的多格式文本控件、连接到数据库的可编辑网格、动态更新显示的图表或天气和旅行信息。如果对控件提供了可视化设计器,则使用Visual Studio的任何页开发人员只需将控件拖至Web部件区域并在设计时对该控件进行配置,而无须另外编写代码。
3)Web应用程序开发。开发完全集成和可个性化设置的Web应用程序(如门户网站)涉及最全面地使用Web部件。可以开发一个允许用户对用户界面和内容进行大量个性化设置的网站,其功能类似于MSN;甚至还可以开发一个可由提供门户网站承载服务的公司或收费ISP提供和使用的打包应用程序。
在Web应用程序方案中,可以为最终用户提供一个完整的解决方案来管理和个性化设置应用程序。这可能包括一组提供站点所需功能的Web部件控件、一组使最终用户可以一致地对用户界面进行个性化设置的一致主题和样式、Web部件控件目录(用户可以从中选择要显示在页上的控件)、身份验证服务以及基于角色的管理(例如,允许管理员用户为所有用户对Web部件控件和站点设置进行个性化设置)。
对于应用程序的各部分,可以根据需要扩展Web部件控件以对环境提供更好的控制。例如,除了为页的主要用户界面创作自定义Web部件控件之外,还可能需要开发一个与应用程序的外观一致的自定义Web部件目录,并使用户可以更灵活地选择向页添加控件的方式。也可以扩展区域控件,以便为它包含的Web部件控件提供其他用户界面选项。此外,还可以编写自定义个性化设置提供程序,以对存储和管理个性化设置数据的方式提供更大的灵活性和更多的控制。
21.3.2 Web部件页面创建示例
一般情况下,如果需要创建一个简单的Web部件页面,大致需要经过如下五个步骤。
1.创建一个Web页面
创建Web部件页面的第一步就是在解决方案里创建一个普通的Web页面,即.aspx页面。需要说明的是,在该Web页面中,无须添加其他任何特别的代码,而只需要按照设计要求设计好页面结构就可以了。如下面的SimpleWebParts.aspx所示:
<%@Page Language="C#"AutoEventWireup="true"
CodeBehind="SimpleWebParts.aspx.cs"
Inherits="_21_1.SimpleWebParts"%>
<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1"runat="server">
<div>
<table width="100%"border="0"cellspacing="0"
cellpadding="0">
<tr>
<td valign="top"width="405px"height="100%"
align="left">
</td>
<td width="100%"height="100%"align="left"
valign="top">
</td>
</tr>
</table>
</div>
</form>
</body>
</html>
2.添加WebPartManager控件
接下来,需要从Visual Studio工具栏里拖入一个WebPartManager控件到该Web页面中,并且只能够向Web页面拖入一个WebPartManager控件。正如前文所说,WebPartManager控件的主要任务是管理Web部件控件、添加和移除Web部件控件、管理连接、对控件和页进行个性化设置、在页面视图之间切换、引发Web部件生命周期事件、启用控件的导入和导出。因此,该控件必须先于其他所有Web部件组件加入到网页中。在这里建议最好将WebPartManager控件放在网页的开头(在服务器端窗体的起始标签内)。如下面的代码所示:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1"runat="server">
<div>
<asp:WebPartManager ID="WebPartManager1"runat="server">
</asp:WebPartManager>
……
</div>
</form>
</body>
</html>
3.添加WebPartZone控件
向页面添加完WebPartManager控件之后,就可以添加可定制区域到Web部件。这些区域也称为Web部件区域,而且每个区域都可以包含任意多的Web部件。
现在,来为上面的Web页面添加两个WebPartZone控件(也就是上面所说的区域)。如下面的代码所示:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1"runat="server">
<div>
<asp:WebPartManager ID="WebPartManager1"runat="server">
</asp:WebPartManager>
<table width="100%"border="0"cellspacing="0"
cellpadding="0">
<tr>
<td valign="top"width="405px"height="100%"
align="left">
<asp:WebPartZone ID="WebPartZone1"
runat="server">
</asp:WebPartZone>
</td>
<td width="100%"height="100%"align="left"
valign="top">
<asp:WebPartZone ID="WebPartZone2"
runat="server">
</asp:WebPartZone>
</td>
</tr>
</table>
</div>
</form>
</body>
</html>
4.添加Web部件
现在,页面包含两个区域,可以分别对它们进行控制。但是,这两个区域中都不包含任何内容,因此现在需要继续为它们创建相关内容,即开始向页面上添加Web部件。
Web部件区域的布局由ZoneTemplate元素指定,在<ZoneTemplate>区域模板内可以添加任意多个ASP.NET控件,包括自定义Web部件控件、用户控件、ASP.NET服务器控件或者自己创建的自定义服务器控件。
为了深入了解Web部件的概念,下面分别在WebPartZone1中添加两个Label控件((mbook与mylink)和一个用户控件SimpleWebParts,而在WebPartZone2中添加一个Label控件。如下面的代码所示:
<%@Page Language="C#"AutoEventWireup="true"
CodeBehind="SimpleWebParts.aspx.cs"
Inherits="_21_1.SimpleWebParts"Theme="MyTheme"%>
<%@Register Src="WebParts/SimpleWebParts.ascx"
TagName="SimpleWebParts"TagPrefix="uc1"%>
<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1"runat="server">
<div>
<asp:WebPartManager ID="WebPartManager1"runat="server">
</asp:WebPartManager>
<table width="100%"border="0"cellspacing="0"
cellpadding="0">
<tr>
<td nowrap="noWrap"valign="top"width="405px"
height="100%"align="left">
<asp:WebPartZone ID="WebPartZone1"
runat="server">
<ZoneTemplate>
<asp:Label runat="server"
ID="mybook"title="我的图书">
<a href="http://www.comesns.com/aspnet">
ASP.NET4程序设计
</a>
<br/>
<a href="http://www.comesns.com/csharp">
易学C#
</a>
<br/>
</asp:Label>
<br/>
<asp:Label runat="server"ID="mylink"
title="我的链接">
<a href="http://www.google.com">
google搜索</a>
<br/>
<a href="http://www.baidu.com">
百度搜索</a>
<br/>
</asp:Label>
<br/>
<uc1:SimpleWebParts ID="SimpleWebParts1"
runat="server"title="天气预报"/>
</ZoneTemplate>
</asp:WebPartZone>
</td>
<td width="100%"height="100%"align="left"
valign="top">
<asp:WebPartZone ID="WebPartZone2"
runat="server">
<ZoneTemplate>
<asp:Label runat="server"ID="Label1"
title="C#基础知识">
<a href="http://www.cnblogs.com/madengwei
/archive/2009/03/10/1408186.html">
C#3.0语言新特性之对象和集合初始化器</a>
<br/>
[摘要]在C#3.0中,一个对象创建表达式……
</asp:Label>
</ZoneTemplate>
</asp:WebPartZone>
</td>
</tr>
</table>
</div>
</form>
</body>
</html>
其中,用户控件SimpleWebParts用于显示一个天气预报。其代码如下所示:
<%@Control Language="C#"AutoEventWireup="true"
CodeBehind="SimpleWebParts.ascx.cs"
Inherits="_21_1.WebParts.SimpleWebParts"%>
<iframe id="ifm1"width="300px"height="332px"
scrolling="yes"marginwidth="0"marginheight="0"
frameborder="0"src="http://weather.qq.com/24.htm">
</iframe>
在这里,为了能够统一WebPartZone控件的显示风格,还定义了一个主题文件MyTheme。其中,MySkin.skin文件代码如下所示:
<asp:WebPartZone SkinID=""runat="server"Font-Size="12px">
<RestoreVerb Description="显示'{0}'"Text="显示"/>
<CloseVerb Description="关闭'{0}'"Text="关闭"/>
<MinimizeVerb Description="最小化'{0}'"Text="最小化"/>
<EditVerb Description="编辑'{0}'"Text="编辑"/>
<DeleteVerb Description="删除'{0}'"Text="删除"/>
<ConnectVerb Description="连接'{0}'"Text="连接"/>
<PartTitleStyle BackColor="#3366FF"BorderColor="#3366FF"/>
<MenuPopupStyle BackColor="#C4FAFB"BorderColor="#5072CB"
ShadowColor="#284286"BorderStyle="Solid"
BorderWidth="1px"GridLines="Horizontal"
Font-Names="Tahoma"Font-Size="9pt"/>
</asp:WebPartZone>
如MySkin.skin文件所示,WebPartZone控件提供了许多有用的属性,详细资料参考msdn。其中,最常用的也最重要的属性如表21-2所示。
5.设置个性化数据存储
到现在为止,一个简单的Web部件页面基本上设计完成了。但是,如果要运行这个Web部件页面,还需要做相关的配置。其中,最重要的就是设置个性化数据存储。
和大多数ASP.NET中的提供程序一样,默认的个性化提供程序是面向SQL Server后台存储而实现的。如果不修改配置文件,它将使用SQL个性化设置提供程序((SlPersonalization Provider)以及Microsoft SQL Server Express Edition来存储个性化设置数据。如果服务器安装了SQL Server Express,则不需要进行任何配置。
图 21-5 自动生成的aspnetdb.mdf
使用Microsoft SQL Server Express Edition基于文件的数据库的一个优势就是它可以被动态创建,不需要用户任何附加的设置。这意味着可以建立一个全新的站点,不用设置数据库就能启用个性化设置特性,当然也能够运行。当最初与网站交互时,系统会在站点的App_Data目录中生成一个新的aspnetdb.mdf文件,如图21-5所示,并且用支持所有默认提供程序所需的表和存储过程来初始化该数据库。
虽然Microsoft SQL Server Express Edition比较简单方便,但是它很少能够作为企业级应用。因为对于企业系统来说,它需要将数据存储到某个被全面管理的、专用的数据库服务器上。因此必须使用完整版本的SQL Server,而在这个时候就必须要安装并配置ASP.NET应用程序服务数据库,并将SQL个性化设置提供程序配置为连接到该数据库。
要想安装并配置ASP.NET应用程序服务数据库,ASP.NET提供一个名为Aspnet_regsql.exe的工具,该工具用于安装SQL Server提供程序使用的SQL Server数据库。其中,Aspnet_regsql.exe工具位于Web服务器上的驱动器:\WINDOWS\Microsoft.NET\Framework\版本号(一般情况下如C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319)文件夹中。该工具既可用于创建SQL Server数据库,又可用于在现有数据库中添加或移除选项。
可以在不使用任何命令行参数的情况下通过运行Aspnet_regsql.exe来运行一个引导你完成如下过程的向导:为运行SQL Server的计算机指定连接信息,并为所有受支持的功能安装或移除数据库元素。还可以将Aspnet_regsql.exe作为命令行工具来运行,以便为各个功能指定要添加或移除的数据库元素。详细步骤如下:
1)双击运行Aspnet_regsql.exe工具,如图21-6所示。
2)在图21-6中单击“Next”按钮,如图21-7所示。可以为所有受支持的功能安装或移除数据库元素。在这里,选择安装数据库元素。
图 21-6 运行Aspnet_regsql.exe工具
图 21-7 选择任务
3)在图21-7中单击“Next”按钮,如图21-8所示。接下来,就可以为运行SQL Server的计算机指定连接信息。设置完连接信息之后,就可以在图21-9中看到所设置的结果。完成安装界面如图21-10所示。
4)现在,打开SQL Server数据库,就可以看到已经安装的aspnetdb数据库,如图21-11所示。
为了能够达到企业级应用,现在必须修改SqlPersonalizationProvider使用的数据库。其实,要修改SqlPersonalizationProvider使用的数据库是非常简单的。首先,打开默认webParts元素在.NET Framework版本的根Web.config(即C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\Config\web.config)文件中的配置。如下面的代码所示:
图 21-8 指定连接信息
图 21-9 显示设置结果
图 21-10 完成安装
图 21-11 已经安装的aspnetdb数据库
<webParts>
<personalization>
<providers>
<add connectionStringName="LocalSqlServer"
name="AspNetSqlPersonalizationProvider"
type="System.Web.UI.WebControls.WebParts.
SqlPersonalizationProvider, System.Web,
Version=4.0.0.0,Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"/>
</providers>
<authorization>
<deny users="*"verbs="enterSharedScope"/>
<allow users="*"verbs="modifyState"/>
</authorization>
</personalization>
<transformers>
<add name="RowToFieldTransformer"type="
System.Web.UI.WebControls.WebParts.RowToFieldTransformer"/>
<add name="RowToParametersTransformer"
type="System.Web.UI.WebControls.WebParts.
RowToParametersTransformer"/>
</transformers>
</webParts>
在上面的配置文件中,发现SqlPersonalizationProvider的配置将连接字符串初始化为LocalSqlServer,这意味着它会在配置文件的<connectionStrings>节中寻找名字为LocalSqlServer的配置项,使用相关的连接字符串去打开到数据库的连接。
默认情况下,这个字符串就是在前面所看到的,意味着它会写入一个本地的Microsoft SQL Server Express Edition.mdf文件。要修改它,必须首先清除掉LocalSqlServer连接字符串集合,然后在Web.config文件中重新设置一个新的连接字符串值(或者,也可以修改机器范围的Machine.config文件,去影响这台机器上的所有站点。但一般情况下不建议这么做)就可以了。配置示例如下面的代码所示:
<connectionStrings>
<clear/>
<add name="LocalSqlServer"connectionString="
server=.;integrated security=sspi;database=aspnetdb"/>
</connectionStrings>
经过上面的配置之后,就可以来运行上面的Web部件页面,如图21-12所示。
图 21-12 示例运行结果
在图21-12中,可以任意最小化、关闭或者还原某个Web部件,而这些个性化设置将会保存到aspnetdb数据库中。当再次打开该Web部件页面时,该页面的设计将与你离开的时候完全一样。
21.3.3 Web部件生命周期
前面的章节已经讲过,每个网页都具有一个生命周期,网页在其生命周期内将执行一系列处理步骤。这些步骤包括初始化、创建控件、还原和维护状态、运行事件处理程序代码以及进行呈现。了解页面的生命周期及其应用于Web部件的方式具有重要意义,这样才能在该周期中的适当阶段实现你的逻辑。具体而言就是,必须让自己熟悉页面的生命周期,才能正确初始化Web部件控件、用个性化设置数据填充属性以及运行任何行为逻辑。
图 21-13 Web部件生命周期(该图来源于msdn)
如图21-13所示,可以简单地把Web部件生命周期分为4个阶段:初始化阶段、初始化完成阶段、加载完成阶段与保存统计信息完成阶段。
在初始化阶段,将执行下列主要任务:
1)将WebPartZone对象注册到WebPartManager控件中。
2)WebPartManager控件加载静态WebPart对象。
3)WebPartManager控件订阅控件生命周期事件。
4)WebPartManager控件为此时已处于控件层次结构中的每个静态WebPart对象均调用TrackViewState方法。
如果需要以编程方式设置GenericWebPart控件的属性,则应在此阶段执行这一操作,这样便可以在适当的时刻(例如,加载个性化设置时)使用这些属性。
在初始化完成阶段将执行下列主要任务:
1)WebPartManager控件加载动态WebPart对象和WebPartConnection对象。需要说明的是,在WebPartManager控件加载动态WebPart对象时,必须将其中的每个对象都置于其他部件所处的相同状态条件下。此同步过程将导致对每个动态WebPart对象均调用TrackViewState方法。
2)WebPartManager控件对静态和动态的WebPart对象调用WebPartPersonalization控件。
在加载完成阶段将执行下列主要任务:
WebPartManager控件激活WebPartConnection对象。在此阶段,可以为未标记为可个性化设置的属性设置值。同时,WebPartManager控件将对其管理的Web部件控件执行一些最终的初始化操作。
在保存统计信息完成阶段将执行下列主要任务:
1)WebPartManager控件从静态和动态的WebPart对象中提取个性化设置信息。
2)WebPartManager控件将静态和动态WebPart对象的个性化设置信息保存在永久存储区中。