用户控件减少了代码的重用性。
一个用户控件就是一个简单的ASP.NET页面,不过他是包含在另一个ASP.NET页面的。
特点如下:
1.扩展名为:.ascx。
2.用户控件中没有“@ page”指令,而是包含“@ Control”指令,该指令对配置及其他的属性进行定义。
3.用户控件不能作为独立文件运行,而是必须像处理控件一样,将它们添加到Asp.net页中。
4.用户控件中没有html,body,或form元素,这些元素不许位于宿主中。
总结性语句:
用户控件与完整的*.aspx文件相似,同时具有网页界面页和服务端代码。创建用户控件的方式与创建*.aspx网页相似,不过用户控件页面的扩展名为ascx,编程者可以根据需要向*.ascx页面中添加必要的HTML标签以及其他现有的WEB服务器控件。完成创建后,编程者可将用户控件嵌入*.aspx页面中作为1个可重复使用的代码单元,并且用户控件可以包含对其内容进行操作的逻辑代码。
在解决方案资源管理器里选中网站,点击右键菜单中的[添加新项],在弹出窗口选择 Web 用户控件,如图所示
点击[添加],在解决方案中可以看到一个新的 Web 用户控件做好了,如图所示:
什么?什么?这就做好了?呵呵,做是做好了,不过没什么功能,现在我们给它加点东西。
编辑TestWebUserControl.ascx,切换到[设计]视图,从工具箱拖动一个 TextBox、一个 Button 和一个 Label 控件到页面上,如图所示:
选中 Button 控件,双击,为其添加 Click 事件的响应代码:
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = TextBox1.Text;
}
OK!到此为止,一个简单的 Web 用户控件搞定了。
3.在 Web 窗体中使用 Web 用户控件
现在我们把做好的用户控件放到窗体上进行测试,选中 Default.aspx 切换到[设计]视图(注意:一定要在设计视图里),在解决方案中拖动 TestWebUserControl.ascx 到页面上,如图所示:
现在我们运行程序,在文本框中填入“Hello World!”,点击 Button ,Label 就会显示相应内容了,如图所示:
停止程序,回到 Default.aspx 的[源]视图,我们来看看刚才的“一拖”,IDE到底为我们做了什么工作。可以发现在代码里增加了一行 @Register 指令,这就是对用户控件引用要做的声明,代码如下:
<%@ Register Src="TestWebUserControl.ascx" TagName="TestWebUserControl" TagPrefix="uc1" %>
这个指令很简单,通过字面就可以看出各属性的含义了。现在我们为了使我们的控件前缀更有意义,而不是什么“uc1”之类的,对这条语句做点修改,代码如下:
<%@ Register Src="TestWebUserControl.ascx" TagName="TestWebUserControl" TagPrefix="Clark" %>
当然,相应的其它地方也要进行修改了,如下:
将
<uc1:TestWebUserControl ID="TestWebUserControl1" runat="server" />改为
<Clark:TestWebUserControl ID="TestWebUserControl1" runat="server" />
这样,以后我们再在此页面使用 TestWebUserControl 控件时前缀自动就变成Clark了,如下所示,我又拖了一个控件到页面里,代码如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register Src="TestWebUserControl.ascx" TagName="TestWebUserControl" TagPrefix="Clark" %>
<!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>
<Clark:TestWebUserControl ID="TestWebUserControl1" runat="server" />
<br />
<Clark:TestWebUserControl ID="TestWebUserControl2" runat="server" />
</div>
</form>
</body>
</html>
当然,通过在 Web.Config 里进行配置也可以注册组件,并且是针对整个网站适用的,这里就不再述。
4.添加属性
下面我们来为做好的控件添加一个属性,添个什么好呢?(本人最大的弱点就是不会写例子。。。)随便来一个吧,编辑 TestWebUserControl.ascx.cs 添加如下代码:
public string LabelContext
{
get { return Label1.Text; }
set { Label1.Text = value; }
}
这样一个可读写的文本属性就做好,太简单了。。。
选中 Default.aspx 切换到[设计]视图,分别选中两个用户控件,在属性查看器里对 LabelContext 进行设置,如图所示:
为了测试该属性的实现,我们再在 Default.aspx 的页面上添加一个 Button 控件,对其 Click 事件添加响应代码,如下:
protected void Button1_Click(object sender, EventArgs e)
{
Response.Write(TestWebUserControl1.LabelContext + " " + TestWebUserControl2.LabelContext);
}
运行程序,点击该按钮,效果如图所示:
5.添加方法
属性加好了,现在再添加一个方法,编辑 TestWebUserControl.ascx.cs ,添加如下代码:
public void ChangeLabelContext(object sender, string value)
{
Label1.Text = value;
}
大家可能注意到,我这个方法有一个 sender ,这是干什么用的呢?别着急,在后面添加事件里会讲到的。
为了测试这个方法,选中 Default.aspx ,切换到[设计]视图,再添加一个按钮,为其 Click 事件添加如下的响应代码:
protected void Button2_Click(object sender, EventArgs e)
{
TestWebUserControl1.ChangeLabelContext(sender, "Hi");
TestWebUserControl2.ChangeLabelContext(sender, "cnblogs");
}
现在运行程序,点击该按钮,效果如图所示:
6.添加自定义事件
属性和方法我们做好了,那么事件呢?
继续编辑 WebUserControlTest.ascx.cs ,首先定义一个代理,代码如下:
public delegate void LabelContextChangedHandler(object sender, LabelContextChangedEventArgs e);
public class LabelContextChangedEventArgs : EventArgs
{
private string labelContext;
public LabelContextChangedEventArgs(string value)
{
labelContext = value;
}
public string LabelContext
{
get { return labelContext; }
}
}
再为 TestWebUserControl 这个类添加一个事件变量和事件触发函数,代码如下:
public event LabelContextChangedHandler LabelContextChanged;
private void OnLabelContextChanged(object sender, LabelContextChangedEventArgs e)
{
if (LabelContextChanged != null)
{
LabelContextChanged(sender, e);
}
}
然后,在 ChangeLabelContext 函数里增加对事件的触发,需要修改原来的代码,如下:
将
public void ChangeLabelContext(object sender, string value)
{
Label1.Text = value;
}改为
public void ChangeLabelContext(object sender, string value)
{
Label1.Text = value;
OnLabelContextChanged(sender, new LabelContextChangedEventArgs(value));
}
OK!到此,我们就完成了对用户控件事件的定义并确定了在何时触发这个事件,下面我们来测试一下。
编辑Default.aspx.cs,先添加一个响应事件的函数,代码如下:
private void TestWebUserControl_LabelContextChanged(object sender, LabelContextChangedEventArgs e)
{
Button tmpButton = (Button)sender;
if (tmpButton.Text == "Button")
{
tmpButton.Text = e.LabelContext;
}
else
{
tmpButton.Text += " " + e.LabelContext;
}
}实现的效果就是将触发事件的 Button 控件的 Text 属性设置成用户控件 LabelContext 的值。
现在,再在页面的 Page_Load 事件的响应代码里将两个用户近件的 LabelContextChanged 和 这个函数“连接”起来就OK啦!代码如下:
protected void Page_Load(object sender, EventArgs e)
{
TestWebUserControl1.LabelContextChanged += new LabelContextChangedHandler(TestWebUserControl_LabelContextChanged);
TestWebUserControl2.LabelContextChanged += new LabelContextChangedHandler(TestWebUserControl_LabelContextChanged);
}
现在我们运行程序,点击页面第二个按钮,效果如图所示这:
7.控件内客户端角本访问服务器控件的方法
这个问题实际上并不属于 Web 用户控件开发的范畴,但实际开发中多多少少会碰到这个问题,所以本着我这“牵牛花”的脾气就把它“牵”进来了,哈哈。
有人要问了,为什么控件内客户端角本访问服务器控件会是一个问题呢,这主要是因为,ASP.NET在将页面解释成客户端浏览器使用的页面时,将用户控件内的服务器控件ID做了一定的改动。如在咱们开发的这个用户控件里有一个 TextBox 控件,ID本来是 TextBox1 ,但在解释后的页面里它变成了 TestWebUserControl1_TextBox1,我们通过在浏览器里查看源代码可以看到,如下所示:
<input name="TestWebUserControl1$TextBox1" type="text" id="TestWebUserControl1_TextBox1" />
也就是说,用户控件被解释成客户端页面后,其中的服务器控件的ID规则是用户控件ID_服务器控件ID,知道这个规律我们就好办了。
编辑 TestWebUserControl.ascx ,切换到[设计]视图,从 HTML 面板拖一个 Input(Button) 控件(注意:这里要的是一个客户端控件)。再切换到[源视图]为其添加 onclick 属性,设成调用一个客户端函数 ShowTextBoxContext ,而这个函数要操作用户控件里的一个服务器控件,完整代码如下:
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="TestWebUserControl.ascx.cs" Inherits="TestWebUserControl" %>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
<input id="Button2" type="button" value="button" onclick="ShowTextBoxContext(<%= TextBox1.ClientID%>)"/>
<script type="text/javascript" language="javascript">
function ShowTextBoxContext(obj)
{
alert(obj.value);
}
</script>
注意这里的<%= TextBox1.ClientID%>,为了获取客户端的对象,我们执行了一个服务端操作,“<%=”和 “%>”之间的代码将会在服务端运行,如此而己,是不是很简单?
现在我们运行程序,在第一个文本框里输入“开发和使用 Web 用户控件,OK!!!”,点击用户控件中刚添加的客户端 Button 按钮,将弹出一个对话框,显示我们填写的内容,效果如图所示:
另:如果使用的是外链角本而非这种内嵌的,那么这种访问方法并不能胜任。我的解决方案是将被访问的服务器控件放到一个 DIV 层里(它本来就是客户端组件),这样在客户端通过先查找到这个 DIV 层,再访问它的处Children 属性,就可以获取到相应的控件了。但由于在用户控件里使用这种外链角本将来在部署上多少有点麻烦,不建议使用,所以就没有列出详细的解决方案。
8.代码下载
下载地址:http://files.cnblogs.com/reonlyrun/WebUserControlTaste.rar
原文地址:http://www.xueit.com/html/2009-03/21_782_00.html
附加:
#include指令:
<!--#include virtual | file ="filename"-->
virtual和file关键字用来包含该文件的路径的类型,
filename是您想包含的文件的路径和名称。
此外,使用virtual关键字指示路径开始于虚拟目录,
而使用 file 关键字指示使用相对路径。
使用#include指令后,即可将功能相似的区域或者代码块作为单独的文件存在,插入到多个需要的*.asp文件中。
这样,相同的代码块可以共用于多个*.asp文件中,避免了经常性重复的代码编写,也大大减轻了维护的复杂度。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。