用户控件
更新:2007 年 11 月
ASP.NET 移动用户控件提供了一种快速高效的方法,使您可以在 ASP.NET 移动网页上创建自己的用户控件。可以将一个或多个控件及其相关逻辑进行组合,然后封装到一个用户控件中,从而在一个移动页中使用其他任何移动页的内容。用户控件和 MobilePage 控件是一样的,但有些例外。
移动用户控件:
文件扩展名必须是 .ascx。
不需要 @ Page 指令。
必须包含 @ Register 指令。
@ Register 指令将别名与命名空间和类关联,以便可以在用户控件中声明移动控件。
ASP.NET 区别用户控件和复合控件。用户控件保持为 .ascx 文本文件,而复合控件在编译后保存在程序集中。在 ASP.NET 移动网页中,用户控件可以包含多个控件,如本主题中的示例所示。
创建用户控件
通过创建带 .ascx 扩展名的文件可创建新的用户控件。下面的代码示例包含一个用户控件,它使用多个标签显示一辆汽车的详细信息。
<%@ Control Language="VB" ClassName="CarControl"
Inherits="System.Web.UI.MobileControls.MobileUserControl" %>
<%@ Register TagPrefix="mobile"
Namespace="System.Web.UI.MobileControls"
Assembly="System.Web.Mobile" %>
<script runat="server">
' Private field of externally defined CarInfo type
Private _car As New CarInfo()
' Public Property for the CarInfo
Public Property Car() As CarInfo
Get
Return _car
End Get
Set(ByVal value As CarInfo)
_car = value
End Set
End Property
</script>
<mobile:Panel ID="Panel1" Runat="server" BreakAfter="true">
<mobile:Label id="Label1" runat="server" BreakAfter="true">
Make: <%# Car.Make %></mobile:Label>
<mobile:Label id="Label2" runat="server" BreakAfter="true">
Model: <%# Car.Model %></mobile:Label>
<mobile:Label id="Label3" runat="server" BreakAfter="true">
Year: <%# Car.Year %></mobile:Label>
<mobile:Label id="Label4" runat="server" BreakAfter="true">
Color: <%# Car.Color %></mobile:Label>
</mobile:Panel>
<%@ Control Language="C#" ClassName="CarControl"
Inherits="System.Web.UI.MobileControls.MobileUserControl" %>
<%@ Register TagPrefix="mobile"
Namespace="System.Web.UI.MobileControls"
Assembly="System.Web.Mobile" %>
<script runat="server">
// Private field of externally defined CarInfo type
private CarInfo _car = new CarInfo();
// Public Property for the CarInfo
public CarInfo Car
{
get { return _car; }
set { _car = value; }
}
</script>
<mobile:Panel ID="Panel1" Runat="server" BreakAfter="true">
<mobile:Label id="Label1" runat="server" BreakAfter="true">
Make: <%# Car.Make %></mobile:Label>
<mobile:Label id="Label2" runat="server" BreakAfter="true">
Model: <%# Car.Model %></mobile:Label>
<mobile:Label id="Label3" runat="server" BreakAfter="true">
Year: <%# Car.Year %></mobile:Label>
<mobile:Label id="Label4" runat="server" BreakAfter="true">
Color: <%# Car.Color %></mobile:Label>
</mobile:Panel>
部署用户控件
创建移动用户控件之后,可以采用下列方式将该控件添加到 ASP.NET 移动网页:
在页上注册该控件,并在标记中声明该控件。
以编程方式将该控件加载到网页中。
若要注册用户控件,请使用 @ Register 指令。若要以编程方式加载控件,请使用 LoadControl 方法。
下面的示例代码演示如何以声明方式在页中注册和使用自定义控件,以及如何以编程方式加载用户控件。
<%@ Page Language="VB"
Inherits="System.Web.UI.MobileControls.MobilePage" %>
<%@ Register TagPrefix="mobile"
Namespace="System.Web.UI.MobileControls"
Assembly="System.Web.Mobile" %>
<%@ Register TagPrefix="carp" TagName="CarControl"
Src="~/CarControl.ascx" %>
<script runat="server">
Protected Sub Page_Load( _
ByVal sender As Object, ByVal e As EventArgs)
' Set the existing car control's data
CarCtl.Car = New CarInfo("TreeCars", "Rooter", _
2003, "Tan")
' Load a new car control and set the data
Dim ccar As CarControl = _
CType(Page.LoadControl("~/CarControl.ascx"), _
CarControl)
ccar.ID = "newCarCtl"
' Set the new car control's data
ccar.Car = New CarInfo("TreeCars", "Climber", _
2001, "Green")
' Add the new car control to form2.Controls
form2.Controls.Add(ccar)
' Bind the data and the controls
DataBind()
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<body>
<mobile:form id="form1" runat="server">
<carp:CarControl ID="CarCtl" runat="server" /><br />
<mobile:Link ID="Link1" Runat="server"
href="#form2" Text="Next" />
</mobile:form>
<mobile:form ID="form2" Runat="server">
<mobile:Link runat="server" id="Link2"
BreakAfter="true"
Text="Return" href="#form1" />
<br />
</mobile:form>
</body>
</html>
<%@ Page Language="C#"
Inherits="System.Web.UI.MobileControls.MobilePage" %>
<%@ Register TagPrefix="mobile"
Namespace="System.Web.UI.MobileControls"
Assembly="System.Web.Mobile" %>
<%@ Register TagPrefix="carp" TagName="CarControl"
Src="CarControl.ascx" %>
<script runat="server">
protected void Page_Load(
object sender, EventArgs e)
{
// Set the existing car control's data
CarCtl.Car = new CarInfo("TreeCars", "Rooter",
2003, "Tan");
// Load a new car control and set the data
CarControl ccar =
(CarControl)Page.LoadControl("~/CarControl.ascx");
ccar.ID = "newCarCtl";
// Set the new car control's data
ccar.Car = new CarInfo("TreeCars", "Climber",
2001, "Green");
// Add the new car control to form2.Controls
form2.Controls.Add(ccar);
// Bind the data and the controls
DataBind();
}
// Toggles the visible form
protected void Command_Click(
object sender, EventArgs e)
{
if (this.ActiveForm == form1)
this.ActiveForm = form2;
else
this.ActiveForm = form1;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<body>
<mobile:form id="form1" runat="server">
<carp:CarControl ID="CarCtl" runat="server" /><br />
<mobile:Command ID="Command1" Runat="server"
OnClick="Command_Click">Next</mobile:Command>
</mobile:form>
<mobile:form ID="form2" Runat="server">
<mobile:Command ID="Command2" Runat="server"
OnClick="Command_Click">Return</mobile:Command>
<br />
</mobile:form>
</body>
</html>
解析 URL
当创建的页访问位于不同目录中的用户控件时,该用户控件中的所有相对 URL 都被解析为相对于该用户控件的目录,而不是相对于该页的目录。典型情况如下所述:
页的地址为 /Default.aspx。
该页包含用户控件“子文件夹/UserControl.ascx”。
该用户控件又包含用户控件 B.ascx。
在这种情况下,B.ascx 被解析为“子文件夹/B.ascx”。通过这种 URL 解析方式,用户控件可以封装任何链接或该控件可能需要的其他相关资源。
以下 URL 被解析为相对于用户控件:
编写控件或控件适配器时,必须确保在必要的地方解析相对 URL。在您的控件和适配器中,调用移动控件的 ResolveUrl 方法,将 URL 解析为相对于包含页或用户控件的目录。适配器基类中的一些帮助器方法自动调用 ResolveUrl 方法来解析超链接。
一种例外情况是,您将 DeviceSpecific 控件包含在一个自定义用户控件中,该用户控件引用 Web.config 文件 <deviceFilters> 节中列出的设备筛选器。在这种情况下,控件使用网页所在目录中的 Web.config 文件,而不是控件的子目录中的 Web.config 文件。
用户控件和窗体引用中的格式设置和链接
可以使用以数字符号 (#) 开头、后跟窗体 ID 的 URL 链接到同一页上的窗体。下面的代码示例使用 Link 控件的 href 属性来指定 URL。
<mobile:Link ID="Link1" Runat="server"
href="#form2" Text="Next" />
典型情况下,有一个用户控件插入顶层的页中。该页和用户控件可能包含一个或多个窗体。该页和每个用户控件上的控件可以引用彼此内部包含的窗体,依照的规则如下:
当网页上的控件引用子用户控件中的窗体时,URL 必须包含窗体的完整唯一的 ID。格式为 ucid:formid,其中 ucid 是用户控件的 ID,formid 是窗体的 ID。
当用户控件内的控件引用窗体时,ASP.NET 首先在用户控件中搜索窗体,然后在它的父级中搜索,依此类推,一直搜索到页级。
例如,假定页包含两个窗体,其 ID 分别为 FormA 和 FormB。此页还包含一个 ID 为 UserControl1 的顶级用户控件。此用户控件包含两个附加的窗体,其 ID 为 FormA 和 FormC。下表显示本方案的可能 URL 及其行为的示例。
控件位置 |
窗体 URL |
行为 |
---|---|---|
在页上 |
#FormA |
链接到页本身上的 FormA。 |
在页上 |
#FormC |
引发异常,因为页不包含任何具有指定 ID 的窗体。(只有用户控件具有这种窗体。) |
在页上 |
#UserControl1:FormA |
链接到用户控件中的 FormA。 |
在用户控件中 |
#FormA |
链接到用户控件中的 FormA,因为 ASP.NET 首先在用户控件本身内搜索。 |
在用户控件中 |
#FormB |
链接到页上的 FormB,因为 ASP.NET 将窗体引用解析为相对于用户控件的父级。 |
创建移动用户控件时的特别注意事项
为移动应用程序开发用户控件时,必须考虑以下问题。
使用预定义样式
要使用户控件获得完全功能的样式支持,在创建移动用户控件时,必须在 .ascx 文件中从 MobileUserControl 类派生它们,而不是从标准的 UserControl 类派生。下面的代码示例演示这一情况。
<%@ Control Language="C#"
Inherits="System.Web.UI.MobileControls.MobileUserControl"
%>
<%@ Register TagPrefix="mobile"
Namespace="System.Web.UI.MobileControls"
Assembly="System.Web.Mobile" %>
Web.config 文件的位置影响其使用
ASP.NET 使用当前运行页的目录来查找该页中控件的配置信息。因此,如果您在 Web.config 文件中定义了特定于设备的筛选器,该 Web.config 文件必须位于 ASP.NET Web 应用程序的移动网页一节的根目录。例如,如果您有一个名为 /Reports/Report1.aspx 的页,该页包含一个名为 /Sales/Inventory.ascx 的用户控件,而且您还有一个包含设备筛选器的 /Sales/Web.config 文件,则 /Sales/Inventory.ascx 控件将在 /Reports/Web.config 文件(而非 /Sales/Web.config 文件)中查找设备筛选器定义。
处理用户控件中的文本
将用户控件中的文本作为 LiteralControl 而不是 LiteralText 控件进行分析。如果用户控件包含文本,并且包含具有内部分页的控件(如 Form),则文本将显示在所有页上。为避免此问题,应将用户控件的内容放在 Panel 控件中,这样文本将由 ASP.NET 页框架分析并作为 LiteralText 控件处理。