上一篇文章介绍了实现3种形式复杂属性的具体方法。为了加深读者对于这些实现方法的理解深度,本文详细讲解了一个利用ASP.NET 2.0技术创建复杂属性的示例。
1. 示例应用
本文所实现的示例很简单,其核心是通过实现自定义服务器控件的连字符形式复杂属性来说明复杂属性的实现方法,其中使用了上一篇文章中介绍的内容。示例效果图如图1所示。
图1
如图1所示,页面显示了公司所在城市、姓名、性别和职务信息。这些内容是定义服务器控件呈现的结果,其中公司所在城市由简单属性City设置,姓名、性别和职务由复杂属性Employee设置,其中包括子属性Name,Sex和Title设置。下面列举了示例应用程序的Default.aspx文件源代码。
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register Namespace="WebControlLibrary" Assembly="WebControlLibrary" TagPrefix="Cp" %>
<!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>
<Cp:Company ID="demo1" runat="server" City="重庆" Employee-Name="小李" Employee-Sex="男" Employee-Title="销售经理" />
</div>
</form>
</body>
</html>
如上代码所示,主要设置了@ Register指令和自定义服务器控件Company。前者用于为页面引入自定义服务器控件Company,从而实现控件在页面中的应用。在自定义服务器控件Company中主要设置了City、Employee-Name、Employee-Sex和Employee-Title。同时,在开发人员编码过程中将会发现,以上4个属性均为Visual Studio 2005的智能感知功能所支持。
另外,读者还可以以另一种非连字符形式设置Company控件属性。具体代码如下所示:
<Cp:Company ID="Company1" runat="server" City="重庆">
<Employee Name="小李" Sex="男" Title="销售经理">
</Employee>
</Cp:Company>
实际上,以上设置Company控件属性的方法与前文利用连字符设置属性的方法是完全一致的。对于所有连字符形式属性,可以任意使用二者之一。如果是基于代码可读性的角度而言,后者比前者的可读性更强一些。
2. 实现方法
上一小节中的Default.aspx页面所包含的Company控件具有3个连字符形式复杂属性。它们是如何实现的呢?实际上,实现这种形式的复杂属性关键是,在自定义服务器控件实现过程中,对复杂属性及其子属性设置特定的设计时元数据。
对于复杂属性而言,主要在该属性实现前设置两个设计时元数据:DesignerSerializationVisibility和NotifyParentProperty。DesignerSerializationVisibility用于指定在设计时序列化组件上的属性时,所使用的持久性类型。NotifyParentProperty可使得属性浏览器中对子属性的修改通知一直上传到对象模型,并在被修改了子属性的控件中产生修改通知。对于子属性的设计时元数据设置比较简单,只需在子属性实现前设置一个NotifyParentProperty即可。
实现自定义服务器控件Company涉及两个文件:Company.cs和Employee.cs。前者是自定义服务器控件的实现主体,其中包括各种属性设置、控件呈现方法RenderContents等等。后者用于实现复杂属性Employee。下面首先列举了Company.cs文件源代码。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebControlLibrary{
[DefaultProperty("Text")]
[ToolboxData("<{0}:Company runat=server></{0}:Company>")]
public class Company : WebControl {
private Employee employee; //实现属性City
[ Bindable(true), Category("Appearance"), DefaultValue(""), Description("公司所在城市") ]
public string City {
get {
string _city = (String)ViewState["City"];
return ((_city == null)?String.Empty:_city);
}
set { ViewState["City"] = value; }
} //实现属性Employee
[ Bindable(true), Category("Appearance"), Description("员工信息"), DesignerSerializationVisibility( DesignerSerializationVisibility.Content), NotifyParentProperty(true) ]
public Employee Employee {
get {
if (employee == null) {
employee = new Employee();
}
return employee;
}
} // 重写RenderContents方法,自定义实现控件呈现
protected override void RenderContents(HtmlTextWriter output) {
output.Write("公司所在城市:");
output.Write(City);
output.WriteBreak();
output.Write("姓名:");
output.Write(Employee.Name.ToString());
output.WriteBreak();
output.Write("性别:");
output.Write(Employee.Sex.ToString());
output.WriteBreak();
output.Write("职务: