13.4 区域和WebPart
有了菜单后,需要确定这个页面上的区域。区域是一个模板化控件,它引用当前区域的所有WebPart,并对这些WebPart的布局、外观和颜色进行同步。ASP.NET页面可以包含多个WebPart- Zone,如图13-3所示。
|
|
图13-3 一个页面上的多个WebPartZone
浏览页面时无法看到区域,但是在其他页面状态下区域是可见的。例如,图13-4显示了正在设计的一个页面,WebPart框架显示了区域,从而能清楚地看出拖放点在哪里。
与我们熟悉的大多数其他模板化控件类似,WebPartZone声明遵循同样的原则。可以声明一些性质来定义区域以及区域中所有WebPart的行为,还可以设置一些元素来定义输出中特定部分的样式,WebPartZone还接受一个ZoneTemplate,其中包含将在此区域默认显示的WebPart的声明(参见代码清单13-6)。

图13-4 设计页面时显示的区域
代码清单13-6 一个简单的WebPartZone控件声明的概略结构
<asp:WebPartZone ID="LeftZone" runat="server"
BorderColor="#CCCCCC" Font-Names="Verdana" Padding="6">
<PartChromeStyle BackColor="#F7F6F3" BorderColor="#E2DED6"
Font-Names="Verdana" ForeColor="White" />
<MenuLabelHoverStyle ForeColor="#E2DED6" />
<EmptyZoneTextStyle Font-Size="0.8em" />
<MenuLabelStyle ForeColor="White" />
<MenuVerbHoverStyle BackColor="#F7F6F3" BorderColor="#CCCCCC"
BorderStyle="Solid" BorderWidth="1px" ForeColor="#333333" />
<HeaderStyle Font-Size="0.7em" ForeColor="#CCCCCC"
HorizontalAlign="Center" />
<MenuVerbStyle BorderColor="#5D7B9D" BorderStyle="Solid"
BorderWidth="1px" ForeColor="White" />
<PartStyle Font-Size="0.8em" ForeColor="#333333" />
<TitleBarVerbStyle Font-Size="0.6em" Font-Underline="False"
ForeColor="White" />
<MenuPopupStyle BackColor="#5D7B9D" BorderColor="#CCCCCC"
BorderWidth="1px" Font-Names="Verdana" Font-Size="0.6em" />
<PartTitleStyle BackColor="#5D7B9D" Font-Bold="True"
Font-Size="0.8em" ForeColor="White" />
<ZoneTemplate>
... WebParts for this zone are referenced here ...
</ZoneTemplate>
</asp:WebPartZone>
要记住,真正显示页面时,页面中WebPart的布局可能与此不同。如果这是一个回送,而且启用了页面布局的编辑,用户有可能将WebPart从一个区域移到了另一个区域。同样,如果页面启用了个性化,WebPart可能出现在另一个区域而不是其原来的位置。
13.4.1 WebPart
前面提到过,WebPartZone中只能有两种控件:
q 标准ASP.NET用户控件(通过页面中一个Register指令引用),其中可以包含HTML、标记、动态内容,或网页中可用的任何其他内容。
q 已编译的.NET程序集(通过页面中的一个Register指令引用),它生成与用户控件或网页同样的内容。
放在区域中的控件就像是放在其他页面上一样。例如,考虑代码清单13-7,这里显示了包含许多控件的两个区域。Contacts、Canteen和Stocks是用户控件,而MSNWeatherWebPart是一个定制服务器控件,其代码在 App_Code文件夹中。
设计WebPart是一个让人很享受的体验,如图13-5所示,在此区域显示为容器,可以在放页面上的任何位置(在这个图中,区域的布局应用了CSS样式)。在区域内部,可以使用表、CSS放置WebPart或者就以直接的流模式来放置。

图13-5 设计WebPart
只需把这些控件放在区域内,它们就会自动成为WebPart。这说明,它们会自动继承WebPart的功能,如有一个标题栏,有最小化、关闭和编辑按钮(取决于页面模式)。区域内的每个WebPart可以在区域内移动,还可以移到其他区域中,也可以最小化或关闭WebPart(假设WebPart允许)。可以注意到,在页面的源代码视图中,Canteen和Stocks的用户控件在其Title属性上显示了一个验证警告。这是因为,用户控件没有Title属性,但是运行时放在WebPartZone中的任何控件都会自动继承WebPart的属性,而Title正是所继承的属性之一。所以在设计时你会得到一个警告,但是在运行时Title属性确实是用户控件的一部分。
代码清单13-7 在WebPartZone中放置控件
<%@ Page Language="C#" ... %>
<%@ Register Src="canteen.ascx" TagName="canteen" TagPrefix="uc2" %>
<%@ Register Src="stocks.ascx" TagName="stocks" TagPrefix="uc3" %>
<%@ Register Src="Contacts.ascx" TagName="ctcs" TagPrefix="uc1" %>
<%@ Register tagprefix="sample" namespace="Sample.Web.UI" %>
...
<asp:WebPartZone ID="LeftZone" runat="server">
<ZoneTemplate>
<uc1:ctcs ID="Contacts1" runat="server" />
</ZoneTemplate>
</asp:WebPartZone>
<asp:WebPartZone ID="RightZone" runat="server">
<ZoneTemplate>
<uc2:canteen ID="Canteen1" runat="server" Title="Canteen" />
<uc3:stocks ID="Stocks1" runat="server" Title="Stocks" />
<sample:MSNWeatherWebPart runat="server" ID="mWeatherWebPart"
Title="MSN Weather" />
</ZoneTemplate>
</asp:WebPartZone>
WebPart自动得到的另一个特性是用户设计页面时的体验。所有WebPart都可以在页面上移动,如图13-1所示。页面处于设计模式时,只需拖动WebPart的标题栏,将其放到新位置上。设计模式中会显示区域,而且会动态地放置一个插入标记,显示出拖放WebPart时会把它放在哪里。为此不用编写任何代码或功能,因为这些由WebPart框架提供。
13.4.2 实现WebPart
用户控件可以作为很不错的WebPart,但是你会发现,对于控件在区域中如何显示你可能需要更多的控制。或者,也许你希望将一个WebPart部署到多个应用,甚至部署到第三方,在这种情况下,可能考虑要编写一个定制服务器控件。或者,也许你只是希望避免出现验证警告,或者希望控制WebPart的默认属性。倘若如此,可以实现IWebPart接口,并在用户控件或定制服务器控件中自行设置属性。
13.4.3 作为用户控件的WebPart
对于用户控件,可以修改后台代码类,使之实现IWebPart,如下所示:
public partial class Contacts : System.Web.UI.UserControl, IWebPart
然后实现这个接口定义的属性。这可以手动完成,也可以让Visual Studio实现默认属性。键入IWebPart后,在I下面会出现一个小的SmallTask,允许你在两种实现方法中做一个选择(参见图13-6)。选择一个实现方法后,会增加这个接口需要的桩属性和方法。对于IWebPart接口,只会增加属性,如下所列:
q CatalogIconImageUrl,定义一个图像的URL,这个图像用于标识一个编目中的WebPart(关于编目的更多内容将在后面介绍)。
q Description,定义WebPart的描述。
q Subtitle,定义WebPart的子标题,子标题要与Title属性连接。
q Title,定义WebPart的标题。
q TitleIconImageUrl,定义一个图像的URL,这个图像出现在WebPart的标题栏中。
q TitleUrl,定义标识WebPart额外信息的URL。

图13-6 自动实现接口
代码清单13-8显示了为Contacts用户控件实现的属性。这里只定义了这个WebPart的默认值,用户对页面完成个性化时可以修改这些默认值。
代码清单13-8 Contacts用户控件WebPart属性
private string _catalogIconImageUrl = "~/images/contact.gif";
private string _description = string.Empty;
private string _subtitle = string.Empty;
private string _title = "Contacts";
private string _titleIconImageUrl = "~/images/contact.gif";
private string _titleUrl = string.Empty;
public string CatalogIconImageUrl
{
get { return _catalogIconImageUrl; }
set { _catalogIconImageUrl = value; }
}
public string Description
{
get { return _description; }
set { _description = value; }
}
public string Subtitle
{
get { return _subtitle; }
}
public string Title
{
get { return _title; }
set { _title = value; }
}
public string TitleIconImageUrl
{
get { return _titleIconImageUrl; }
set { _titleIconImageUrl = value; }
}
public string TitleUrl
{
get { return _titleUrl; }
set { _titleUrl = value; }
}
实现IWebPart接口对于用户控件来说不是必要的,不过这样确实有好处,可以对属性的默认值有更大程度的控制。
13.4.4 作为定制控件的WebPart
实现WebPart的另一种方法是编写一个定制服务器控件,在这种情况下,定制服务器控件要继承自WebPart,WebPart类提供了WebPart的基本实现。MSN Weather WebPart非常简单,因为它只是写出一些控件以及从MSN获取天气信息的客户脚本。代码如代码清单13-9所示。
代码清单13-9 MSN Weather WebPart
public class MSNWeatherWebPart : WebPart
{
private const string HtmlFormat = @"
<div id=""weatherView""></div>
<script id=""weatherScript""
language=""javascript""></script>
<script language=""javascript"">
function CreateWeather(sAcid) {{
var oData = window['weatherScript'];
if (sAcid != '') {{
oData.onreadystatechange = ShowWeather;
oData.src =
'http://www.msnbc.com/m/chnk/d/weather_d_src.asp?acid='
+ sAcid;
}}
}}
function ShowWeather() {{
if (typeof(makeWeatherObj) != 'undefined') {{
var oWea = new makeWeatherObj();
var sTmp =
'<b>Current Weather Conditions</b><hr size=1>' +
'<table cellpadding=2 cellspacing=0 border=0><tr>' +
'<td valign=""middle"">' +
'<img src=""http://www.msnbc.com/m/wea/i/36/' + oWea.swCIcon +
'.gif"" align=absmiddle></td>' +
'<td>'+ oWea.swCity + ', ' + oWea.swSubDiv + '<br>' +
oWea.swTemp + '°F</td></tr></table>' +
'<a href=""http://www.weather.com"">More weather information</a>';
document.all['weatherView'].innerHTML = sTmp;
}}
}}
CreateWeather('{0}');
</script>
";
private string _zipCode;
public string ZipCode
{
get {return _zipCode;}
set {_zipCode = value;}
}
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
writer.Write(String.Format(HtmlFormat, _zipCode));
}
}
这段代码实现了一个标准服务器控件,这个控件将显示一些内容,其中只包括HTML和JavaScript。ZipCode属性标识了显示哪个地区的天气,在本章后面你会看到可以把这个属性替换为与其他WebPart的连接,从而自动提供ZipCode 。
13.4.5 WebPart Chrome和样式
WebPart 的非内容区(边框、标题栏、打开/关闭/最小化按钮等等)统称为窗口的chrome。WebPart标题栏上的单个按钮和命令链接(以及各WebPart标题栏下拉列表中可用的链接)会执行WebPart技术实现的动作。这些按钮或链接及其外观,以及它们执行的动作定义为一系列Verb,如图13-7所示。
|
|
|
|
|
|
图13-7 WebPart chrome和样式
WebPart的chrome可以改变,可以在WebPart本身改变,也可以在区域中改变,对于后一种情况,(区域中)所有WebPart将继承相同的chrome。例如,考虑代码清单13-10,这里显示了一个区域的定义。利用一些元素可以定义不同的verb(即区域中WebPart上能发生的动作)。在这个例子中,每个verb定义了一个在标题旁显示的图像,并设置verb的一个描述,它显示为一个工具提示。每个verb还有一个相关的样式,允许修改外观。
代码清单13-10 改变WebPart的Chrome
<asp:WebPartZone ID="LeftZone" runat="server" style="float:left;">
<ZoneTemplate>
<uc1:Contacts ID="Contacts1" runat="server" />
</ZoneTemplate>
<CloseVerb ImageUrl="~/Images/CloseVerb.gif"
Description="Removes the WebPart from the page" />
<MinimizeVerb ImageUrl="~/Images/MinimizeVerb.gif" />
<RestoreVerb ImageUrl="~/Images/RestoreVerb.gif" />
<EditVerb ImageUrl="~/Images/EditVerb.gif"
Description="Edit the properties of the WebPart" />
<MenuVerbStyle BorderColor="#5D7B9D" BorderStyle="Solid"
BorderWidth="1px" ForeColor="White" />
</asp:WebPartZone>
可以在每个页面中设置chrome,也可以在各个区域中设置,或者利用主题来设置(关于主题的更多内容参见第12章),使某些WebPart不在页面中显示。这样会使页面更清楚,更易于阅读,使你不会被大量样式所淹没。
应用样式可以在代码中完成,也可以在设计视图中使用AutoFormat选项完成。样式有很多,涵盖整个WebPart、chrome、verb菜单、verb菜单中的单个项,等等。
13.4.6 WebPart Verb
我们已经看到,verb能标识WebPart允许的动作。并不是所有verb都一直能用,因为其可用性取决于页面的状态。例如,如果WebPart已经最小化,minimize就不可见。所允许的verb包括:
q Close,关闭一个WebPart,将其从当前页面删除,并移到页面编目。
q Connect,将WebPart连接到另一个WebPart。
q Delete,从页面删除WebPart,但不移到编目中。
q Edit,编辑WebPart的外观和布局。
q Export,将一个WebPart的属性导出到一个文件。
q Help,显示一个WebPart的帮助。
q Minimize,最小化WebPart,只显示标题。
q Restore,将WebPart从其最小化状态恢复。
每个verb可以有其各自的属性集,如标题或图像,它们可能导致区域出现,这取决于所选择的verb。由于verb自动增加到WebPart,所以无需编写任何代码,不过如果将WebPart构建为定制服务器控件,则可以直接与verb交互,甚至创建你自己的verb。







