在ASP.NET 的服务器端控件中有三种关于 ID 的属性

在ASP.NET 的服务器端控件中有三种关于 ID 的属性,即 ID, ClientID 和 UniqueID。

ID 表示控件的服务器端编程的标识符,我们写"服务器端的代码",就要用到这个 ID, 通过这个 ID
可以在服务器端对服务器端控件的属性、方法和时间进行编程访问。(可写)

ClientID 表示由服务器端生成的客户端控件的ID,"经常用于在客户端脚本中访问服务器控件所呈现的 HTML
元素"。一般情况下与服务器端的 ID 相同,有时,不能为控件生成唯一的名称,例如,如果Repeater 空间在它的某个模板中包含一个 Label
控件,则将在客户端生成多个该 Lable 的 HTML 元素, 为防止命名冲突,ASP.NET 为各个服务器控件生成一个唯一的 ClientID
,ClientID 通过将子控件的父控件的 UniqueID 值与控件的 ID 值连接生成,各个部分之间以下划线 _ 连接。(只读)

UniqueID
用于获取服务器控件的唯一的、以分层方式表示的标识符。当将控件放置到重复控件(Repeater、DataList和DataGrid)中时,将可能生成多个服务器端的控件,这就需要区分服务器端的各个控件,以使它们的
ID 属性不冲突。UniqueID 通过将子控件的父控件的 UniqueID 值与控件的 ID 值连接生成,各个部分之间以IdSeparator
属性指定的字符连接。默认情况下, IdSeparator 属性为冒号字符 (:)。此属性为在 .Net
Framework2.0种新增加。js与aps.net交互一般情况下使用<%=控件ID.ClientID%>就OK了,但如果用到母版页(MasterPage)则要使用UniqueID获得获值。(只读)

例如,创建以下 ASP.NET 服务器控件:

<asp:textbox id="TextBox1" runat="server" text="Sample Text"
/>

ClientID 属性被设置为 TextBox1,在基于 HTML 的浏览器中,其结果元素与以下所示类似:

<input name="TextBox1" type="text" value="Sample Text"
id="Text1" />

可以使用这些属性在客户端脚本中引用服务器控件。通常,必须在客户端脚本中用完全限定引用来引用控件;如果控件是页面中 form
元素的子控件,则一般使用document.forms[0].TextBox1.value = "New value"在客户端脚本中引用控件。

有些控件将子控件呈现在页面中。这些控件中包括数据列表控件(如GridView、DetailsView、FormView、DataList
和 Repeater 控件)、用户控件和 Web 部件控件。可以看到,在这些情况下,子控件可能不具有唯一的
ID,这可能是因为子控件是在某个模板中定义的,该模板会为每个数据行(数据列表控件)生成新的控件实例,也可能是因为可以从外部源(用户控件和 Web
部件控件)将父控件添加到页面中对于每个子控件:控件的 UniqueID 被呈现为 name。控件的 ClientID 被呈现为 id 属性。

ClientID 和 UniqueID 属性都基于原始的 ID
属性,并用足够的信息进行了修改,以保证页面中结果的唯一性。ClientID的值可在客户端脚本中引用。如果在浏览器中显示一个具有命名容器的页面,则可以查看该页面的源文件,从中找到唯一的
ID,这些 ID 作为命名容器子控件的 name 属性和 id 属性生成。但是,建议不要依赖于直接引用在浏览器中看到的 ID。因为用于生成子控件唯一ID
的公式可能会发生变化,应当获取子控件的 ClientID
属性值,并用该值来引用该子控件。例如,您可能会在页面中动态创建客户端脚本。如果客户端脚本引用一个子控件,则应获取该子控件的 ClientID
属性,并将其嵌入到动态脚本中。

例2:

假设有子控件:

<asp:TextBox ID = "textboxInfo" runat ="server" Text = "Test
Text box" name="haha"></asp:TextBox>

那么我们可以在脚本中这样写

var tempt = ‘<%=textboxInfo.ClientID%>‘;

var controlname = document.getElementByIdx_x(tempt).name;

var controlid = document.getElementByIdx_x(tempt).id;

  还有一个问题我们需要注意:在使用UniqueID和ClientID的时候要小心点,千万不要“迫不及待”地使用了这些属性,在运行的过程中可能会碰到一些让人头疼的问题.

注意

除了用来分隔 ID 值的是下划线字符而不是 IdSeparator 属性指定的字符以外,为控件生成的 ClientID 值与
UniqueID 值相同。默认情况下,IdSeparator 属性设置为冒号字符 (:)。由于 ClientID
值不包含冒号字符,因此,它可以用于不支持包含冒号的 ID 的 ECMAScript。ClientID 值经常用于以编程方式访问为客户端脚本中的控件呈现的
HTML 元素。有关详细信息,请参见 ASP.NET 网页中的客户端脚本。

总结:

ID,用于server端编程引用控件,没有对应的client值,即不呈现到html中。

UniqueID,

asp.net引擎按控件树层次生成的分层形式限定的标志符,连接符默认为 $ (美元符号)【注:MSDN说默认为 :
(冒号),实际是 $ ,可能文档有误吧】,此连接符在asp.net 2.0 中由属性 IdSeparator
指定,在client中呈现为html元素的name属性

此属性主要用来提交(PostBack)客户端数据,如Request.Form[someControl.UnqiueID]

ClientID,

由父控件的UnqiueID连接本身ID而成,但是连接符不一样,默认为   _
(下划线),此连接符在asp.net 2.0 中由属性 ClientIDSeparator
指定,在client中呈现为html元素的id属性,此属性主要在客户端教本中使用,如 var o =
document.getElementByIdx_x(‘<% = someControl.ClientID %>‘);

关于 UniqueID的层次分隔符号,1.x 中为 :(冒号),而 2.0 已实现为 $(美元符),主要原因可能是
javascript 中标识符是允许 $,而不允许 : 的。(当你偷懒的时候,可以在 js 中直接使用表单元素的 name属性应用该表单元素,而不用
document.getElementsByName 或者 document.getElementByIdx_x,不推荐:)

ASP.NET 使用的回发机制(简单版本)是通过一个原型为
__doPostBack(<ControlUniqueID>, <CommandArgs>) 的 javascript 函数

function __doPostBack(eventTarget, eventArgument) {

if (!theForm.onsubmit ||
(theForm.onsubmit() != false)) {

theForm.__EVENTTARGET.value
= eventTarget;

theForm.__EVENTARGUMENT.value
= eventArgument;

theForm.submit();

}

}

此函数的第一个参数 <ControlUniqueID> 对应引起页面回发控件的客户端 name 属性/服务端
UniqueID 属性,当用户引发一个事件,如点击按钮,选择列表框的某一项,首先通过 _doPostBack 函数将此值存在隐藏域中,然后提交页面。

在服务器端,ASP.NET 引擎通过 HttpRequest.HttpMethod 确定请求是否为 post
方式,若是,则检索HttpRequest.Request.Form["__EVENTTARGET‘],
获取引发回发的控件唯一标识符,并在页面控件集合层次中查找,若找到此控件,则将在适当阶段引发服务器端事件。

另补充控件变化规律如下:

控件名字发生变化是因为
INamingContainer这个接口。这个接口没有任何方法,仅只作为一个标记。ASP.NET维护控件name和id生成的规律是:NamingContainer爷爷$NamingContainer爸爸$该控件的ID。id则一般将$换为"_"。

你把控件直接放到form下,它头顶唯一一个NamingContainer是Page,但是这个是特殊的逻辑,不会生成__Page_控件名,所以就只剩控件名了,于是ID看起来没有变化。

当你把控件放到Repeater中时,Repeater自己被INamingContainer标记,同时,每一次循环,它会把模板内的控件重新生成一遍,同时生成一个RepeaterItem,
把这些根据模板生成的控件加入RepeaterItem的子控件。这个RepeaterItem也是一个NamingContainer. 于是控件中就会带有:

RepeaterID(Data)_RepeaterItemID(ctl + 号码)_控件ID.

不过非runat=server控件因为不由ASP.NET维护, 不会发生变化.
UserControl.ascx由于其基类也是一个NamingContainer, 所以如果你把控件放入.ascx, 然后在页面上引用,
则前面又会多一层UserControl的ID.

通过controls集合访问服务器控件:

在VS2005中新建一个.aspx文件,打开HTML页会发现一个原先的声明从

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
>

变成了

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">!

很早以前就称的HTML的接班人XHTML,现在MS终于要将它扶正了..

这样在写HTML代码时就要注意了,

如:

<font>

<div>

</font>

</div>

是无法在Vs2005中的Design模式中正确显示的[很明显的错误,但在HTML可以正常显示]..
,XHTML的语法比HTML严格的

而关于XHTML和HTML的区别,如果不是非常明白http://www.blueidea.com/tech/site/2004/1911.asp这个文章可以参考一下。

Form

Form新添加了几个功能比较有用的是defaultbutton、defaultfocus。从字面的意思大家就可以理解了以前在ASP.NET中让人头痛的默认提交表单按钮和设置焦点在ASP.NET
2.0已经提供了,不用象以前那样自己写javascript来控制了

关于焦点在也可以代码中通过 this.SetFocus()来设置了,看得出来ASP.NET2.0是设计是多么的细致。

Header

在代码中可能通过

this.Header.Metadata.Add("taye", "value");

this.Header.Title = "value";

this.Header.LinkedStyleSheets.Add("style.css");

来控制Title,Meta,Style等[好象LinkedStyleSheets只能是text/css???]

this.Header.StyleSheet.RegisterStyle()

方法将一个style内嵌到网页中去.

这样页面几乎所以部分都可以得到控制了

有些人也许会想那<html>和<body>呢

我们先来运行一下面这个代码.

private void Page_Load(object sender,
EventArgs e)

{

foreach (Control
ctl in Page.Controls)

{

Response.Write(ctl.ToString()
+ "<BR/>");

LiteralControl
lc = ctl as LiteralControl;

if
(lc != null)

{

Response.Write(lc.Text);

}

}

}

你将会看到一个正常页的有如下五个控件

System.Web.UI.LiteralControl

System.Web.UI.HtmlControls.HtmlHead

System.Web.UI.LiteralControl

System.Web.UI.HtmlControls.HtmlForm

System.Web.UI.LiteralControl

而三个LiteralControl的控件的内容分别为

System.Web.UI.LiteralControl

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >

System.Web.UI.LiteralControl

<body>

System.Web.UI.LiteralControl

</body>

</html>

所以如果你要对body或<!DOCTYPE..>或<html>进行控制那你就找到这相应的控件以后再进行相应的修改吧。只要对

LiteralControl.Text进行修改就可以.

--------------------------------------------------------------------------

从外部的js文件中获取ASPX页面的控件ClientID

前言

当使用MasterPage、UserControl等容器时,为了避免控件的重复命名,asp.net会自动将容器中的控件生成一个ClientID(Control
Tree中的可生成,否则不会生成)。

例如:ContentPlaceHolder1中的Button1默认情况下会生“ctl00_ContentPlaceHolder1_Button1”的ClientID。我们在Render出来的mark
up中看到的也是这些ClientID。所以,当我们使用JavaScript对控件元素进行操作的时候,必须使用ClientID来对控件进行查找。

Inline情况下的解决方案

如果JavaScript代码写在.aspx文件中时,也就是Inline
Script时。在页面生成的时候,我们能够通过绑定机制将控件的ClientID绑定到页面Mark up中,故可使用:

-->document.getElementByIdx_x("<%=Me.txtTest.ClientID
%>" )

来获取一个控件的真实引用,当然,FindControl等方法也可以写在<%=...%>中用来绑定服务端数据到客户端。

external JS情况下的解决方案

然而,部分情况下,为了解耦,我们常常把JavaScript单独写在.js文件中,再引用到aspx文件中去。这种情况下,.js文件内的代码不能通过<%=...%>来进行服务端数据的绑定,所以上面的方法是不能用的。

此时简单点的解决方案就是直接在JavaScript中写控件的ClientID,但这样增加了JS文件和ASPX的耦合度,非常不推荐使用。

我常用的方法有两种,在此抛砖引玉:

案例:

Default5.aspx是MasterPage.master 的内容页,本例中的主要文件。

JScript.js是一个外部的js文件,用来处理JavaScript操作。

Button1是Default5.aspx中的一个<ASP:Button>,用来显示效果。

Button2是Default5.aspx中的一个<input
type=button>,用来触发JavaScript。

需求:点击Button2,将Button1上的文本改成“from extended js”

方案一:使用内联JS访问器

要想在外部JS中获得ASPX动态生成的ClientID,可以通过在ASPX页面中添加访问器的方式来实现,类似OO语言中的属性:

我们在Default5.aspx中添加如下代码:作用:①声明getClientId访问器,并注册Button1的ClientID。②引用JScript.js文件

--><script type="text/javascript">

function getClientId()

{

var paraId1 = ‘<%=
Button1.ClientID %>‘;

return {Id1:paraId1};

}

</script>

<script type="text/javascript"
src="JScript.js"></script>

接下来,我们在JScript.js中,就可以这样来实现需求:

-->function ChangeText()

{

var
btn=document.getElementByIdx_x(getClientId().Id1);

btn.value="from extended js";

}

getClientId().Id1
貌似很OO,而且还支持VS2008很蹩脚的JS智能提示,打上“.”之后就可以在提示中选择Id1了。

如果有多个控件需要注册,只需将他们注册到访问器中即可,下面是一个完整的Demo代码:

></script>//引用外部js

</asp:Content>

<asp:Content ID="Content2"
ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">

<asp:TextBox ID="TextBox1"
runat="server"></asp:TextBox>

<asp:Button ID="Button1"
runat="server" Text="Button" />

<input id="Button2" type="button"
value="button" onclick="ChangeText();" />

</asp:Content>

function ChangeText()

{

var
btn=document.getElementByIdx_x(getClientId().Id1);

btn.value="from extended js";

var
btn=document.getElementByIdx_x(getClientId().Id2);

btn.value="from extended js";

}

方案二:使用JS全局变量

还有一种方法也比较OO,就是使用JS全局变量,同样,也需要在Default5.aspx中添加一段JS代码,作为全局变量,来提供ClientID:

--><script type="text/javascript">

var globals = {};

globals.controlIdentities = {};

globals.controlIdentities.someControl1 =
‘<%= Button1.ClientID %>‘;

globals.controlIdentities.someControl2 =
‘<%= TextBox1.ClientID %>‘;

</script>

<script type="text/javascript"
src="JScript.js"></script>

接下来,我们在JScript.js中,就可以这样来实现需求:

-->function ChangeText()

{

var
btn=document.getElementByIdx_x(globals.controlIdentities.someControl1);

btn.value="from extended js";

}

globals.controlIdentities.someControl1,同样,也支持VS2008很蹩脚的JS智能提示,打上“.”之后就可以在提示中选择someControl1了。下面是一个完整的Demo代码:

></script>

</asp:Content>

<asp:Content ID="Content2"
ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">

<asp:TextBox ID="TextBox1"
runat="server"></asp:TextBox>

<asp:Button ID="Button1"
runat="server" Text="Button" />

<input id="Button2" type="button"
value="button" onclick="ChangeText();" />

</asp:Content>

function ChangeText()

{

var
btn=document.getElementByIdx_x(globals.controlIdentities.someControl1);

btn.value="from extended js";

var
txt=document.getElementByIdx_x(globals.controlIdentities.someControl2);

btn.value="from extended js";

}

结束语:

在上面两种方法中,也没有真正的实现aspx和js的完全解耦,所以,在js文件中,最好还是加上:

-->///<reference path="Default5.aspx"/>

上面的方法是我常用的,今天仓促的总结了一下,希望在此能够抛砖引玉,谢谢!

--------------------------------------------------------------------------

ASP.Net中如何使用ClientID

ASP.Net
提供了代码和页面分离的机制,在大多数情况下,这种机制工作得非常好。但是,如果需要使用客户端java脚本来做些工作,你就会遇到麻烦了。问题出在你在设计阶段为server端控件设置的ID值和页面运行时控件实际的ID值不一致。例如,新建一个Web
site,增加一个 aspx page,在页面上加入一个text box控件:

<asp:TextBox ID="mytext"
Runat=server></asp:TextBox>

运行这个页面,从View source中会看到运行时的结果:

<Input name="mytext" type="text" id="mytext" />

这时我们看到设计阶段的ID值和运行时控件的ID值是一样的,没有问题,这是因为这是一个单纯的aspx页面。如果在页面中包含一个用户自定义的web
control或使用了master pages (ASP.NET 2.0),情况就不乐观了。

我们增加一个新的user control名为mycontrol.ascx. 在mycontrol.ascx中加入同样的text
box。再把这个自定义控件加入到一个aspx 页面, 将此控件的ID设置为myControl. 在浏览器中运行这个页面,得到的html是这样的:

<Input name="myControl:mytext" type="text"
id="myControl_mytext" />

text box控件的设计阶段ID=
mytext,但运行时得到的ID=myControl_mytext。也就是在原来的ID前面增加了包含text
box控件的容器myControl的ID。在使用master pages时,所有的aspx 页面都是被包含在一个容器中的,
而且还常常会有容器的嵌套。如果在客户端使用JavaScript去按照ID查找控件就会失败。解决这个问题可以有多个方法。

最简单的:

<script language="javascript" type ="text/javascript>

var x=<%
Response.Write("‘"+myControl.ClientId+"‘;" ) %>

function
doSomething()

{

Var
myControl=document.getElementByIdx_x(x);

}

</script>

这种方法对于一个两个控件比较适用。不过由于必须在aspx页面中设置,不能将javascript集中起来管理了。

那么,有没有可以不进行硬编码的方法呢?本文提供了一种方法,可以使用ASP.Net现有技术实现,并且适合所有的ASP.Net
framework版本。

解决方案

关键是创建一个不会被服务器端修改的客户端控件。在自定义控件上增加一个hidden input,将它设为literal
server side control:

<input type=hidden id="ctrlPrefix" name="ctrlPrefix"
value=‘<asp:Literal Runat=server
ID=ctrlPrefix></asp:Literal>‘>

还要注意,这个hidden
input控件需要加入到控件容器里面。因为我们后面要用它来得到控件的ID。在后台代码中对Page_Load 事件加入如下处理:

string []elm
=ctrlPrefix.ClientID.Split(‘_‘);

ctrlPrefix.Text = ctrlPrefix.ClientID.Replace(elm[elm.Length -
1],"");

我们得到控件的client
id,包含了控件的ID加上控件容器的ID作为前缀。第二行代码将ctrlPrefix.ClientID的后面一段去掉,得到容器的ID前缀,返回值包含了_。编译后运行这个页面,结果如下:

<input name="myControl:mytext" type="text"
id="myControl_mytext" /><input type=hidden id="ctrlPrefix"
name="ctrlPrefix" value=‘myControl_‘>

现在,hidden input中已经保存了容器的ID前缀。下面,我们用JavaScript来利用hidden
input处理控件查找。

增加一个新的方法getCrtlPrefix()

//returns the container prefix as all controls have that on
their ids

function getCrtlPrefix()

{

var
prefix;

var        objCrtlPrefix
= document.getElementByIdx_x("ctrlPrefix");

if
(objCrtlPrefix)

prefix
=
objCrtlPrefix.value;

return
prefix;

}

这个方法得到hidden input的值并返回,这样我们就得到了ID的前缀。第二个方法用来查询空间

function readValue(ctrlName)

{

var prefix =
getCrtlPrefix();

var        objCrtl =
document.getElementByIdx_x(prefix + ctrlName);

if
(objCrtl)                 alert
( "Prefix: " + prefix + " - value: " + objCrtl.value);

else                 alert("not
found!");

}

这个方法显示textbox控件的值。你会注意到,这里调用了getCtrlPrefix来计算textbox控件的ClientID。
我们可以增加一个按钮来调用这个方法:

<input type=button value="Read Value"
onclick="javascript:readValue(‘mytext‘)">

这个html button会调用readValue。最后,把这个javascript的js文件加入aspx中。

<script language="JavaScript"
src="mycontrol.js"></script>

运行这个页面,在text box中输入写数据,然后点击按钮,会出现一个消息对话框来显示ID前缀以及text
box中的数据。

在ASP.NET 的服务器端控件中有三种关于 ID 的属性,布布扣,bubuko.com

时间: 2024-08-08 08:40:44

在ASP.NET 的服务器端控件中有三种关于 ID 的属性的相关文章

asp.net在用户控件中使用ClientScript

在用户空间中调用ClientScript.RegisterClientScriptBlock方法 ClientScript的命名空间是System.Web.UI.Page,并且要实例化之后的Page才能条用ClientScript. 用户自定义空间不是继承自Page,因此不能直接使用ClientScript这个类.如果要使用这个类,需要通过找到调用页面对象的方式.具体做法: this.Parent.Page 找到这个对象之后,就可以像在普通页面中一样,自由调用System.Web.UI.Page

Asp.Net 之 服务器端控件与客户端控件的区别

服务器控件,即Asp.Net的控件,控制这些控件必须经过服务器处理,然后响应用户,代码在服务器端解释执行,生成根据用户的浏览器而定的html元素. 客户端控件,即普通Html控件,使用script控制操作,由客户端浏览器解释执行. 服务器控件需要回发执行,当首次打开页面时,需初始化.由runat属性指示的,runat的值有且仅为一值"server".通过添加runat属性,一般的HTML控件可以被很方便地转换到服务器端运行,下面是一个简单的例子:<input type="

asp.net关于Repeater控件中的全选,批量操作

今天在Repeater控件中碰到一个全选的操作,于是上网查了一下,找到一个觉得比较好,便记录下来, 界面代码简化之后(全选操作): <script type="text/javascript"> function SelectAll(parentChk, ChildId, bigControlID) { var oElements = document.getElementsByTagName("INPUT"); var bIsChecked = par

asp.net 在repeater控件中加按钮

在repeater中加入方法有两种方法: 第一种:是对repeater控件的行添加OnItemCommand事件,添加方法也是有两种 1.在设计页面中,选中repeater控件右击==>属性==>属性栏中的事件标签(闪电符号)==>双击ItemCommand 2.在写代码,也是可以实现. <asp:Repeater ID="rptDataList" runat="server" onitemcommand="rptDataList_

webBrowser控件中获取元素 的class 属性值

html 代码如下: <TR id="t030006" class="sr plus selected"> <TD><INPUT id=cvrgNo030006 value=030006 readOnly CHECKED type=checkbox jQuery1456994811776="96"></TD> <TD>车辆损失险 </TD> <TD style=&quo

ASP.NET服务器端控件和HTML控件的比较 (转)

区别:服务器端控件都会有个runat="Server"属性,这样才能够在后台对其进行修改,也就是在cs代码里面能对其进行修改.例如,当你放个HTML控件时,在CS代码中引用不出控件名,但加上runat="Server" 后在CS代码中就能引用该控件了. 其实ASP.NET 的服务器控件解析后最终返回到前台还是HTML控件.例如当你建个页面并放一个asp:textbox上去,然后运行页面,查看页面源文件就会发现放上的服务器控件变成了HTML的inupt type=&q

ASP.NET--Web服务器端控件和Html控件

今天学习总结了一些相关概念和知识. 之前无论是做 单机的winform 还是 CS的winform 感觉,不到两年下来感觉还可以,虽然API有很多,但是还是比较熟悉基于WINDOWS消息机制的编程,但是现在网络硬件设施更新之快,BS 开发优势之大,不过需要的技术方面倒是得扩宽许多,JavaScript,CSS,Html都需要了解掌握,除webForm之外,对于现今主流的MVC更是需要学习. 概念: asp.net控件服务端控件  --> 响应服务端事件 HTML控件客户端控件   -- > 

Flex 列表控件中的操作

主要操作包括:显示提示,使用图标,编辑列表条目中数据. 1.使用数据提示: 当鼠标停留在条目上时,可以显示该条目的相关数据提示. 当利用滚动条时,可以显示滚动条的相关提示. 在列表控件中使用showDataTips和showScrollTips属性指明是否显示条目提示和滚动条提示. 1 <?xml version="1.0" encoding="utf-8"?> 2 <s:WindowedApplication xmlns:fx="htt

javascript获取asp.net服务器端控件的值

代码如下: <%@ Page Language="C#" CodeFile="A.aspx.cs" Inherits="OrderManage_A" %> <%@ Register Src="../UserControl/CtrlCalendar.ascx" TagName="CtrlCalendar" TagPrefix="uc1" %> <html>