webform用户控件
一,用户控件与页面的区别
1.扩展名:用户控件——.ascx 页面——.aspx
2.内容:页面有完整的HTML标记,用户控件没有
3.声明指示符:页面<%@ Page ...%> 用户控件<%@ Control ...%>
4.类的派生:页面派生自Page,用户控件派生自UserControl
5.页面可以独立运行,用户控件不能,它只能放在页面中才能运行
二,用户控件的好处
1.最大限度的实现代码重用,省去重复写代码的麻烦
2.团队合作时可以实现分工开发,节省时间
3.结构良好
三,用户控件使用过程中的几个难点
1.交换信息
(1)从外向内操作——在页面中操作用户控件里面的控件
I,事先给用户控件定义属性,通过属性给用户控件赋值
案例:在页面中点击按钮将文本框中的值送到用户控件里的Lable中去
先在用户控件中定义一个LableValue的属性
public string LabelValue { get { return Label1.Text; } set { Label1.Text = value; } }
在页面中编写按钮点击的代码
protected void Button1_Click(object sender, EventArgs e) { //把文本框的值取出来 string s = TextBox1.Text; //送到用户控件的label中去 WUC1.LabelValue = s; }
II,使用用户控件对象的FindControl()方法找到它里面的控件,强制转换出来对它进行操作
protected void Button2_Click(object sender, EventArgs e) { //把文本框的值取出来 string s = TextBox1.Text; //送到用户控件的label中去 Label lbl = (Label)WUC1.FindControl("Label1"); lbl.Text = s; }
(2)从内向外操作——在用户控件中操作它所在页面的控件
I,使用Session传递
a.在按钮点击时候,把值放到Session中去。
b.重写页面的OnLoadComplete方法,在这个方法中把值从Session中取出来。
注意:不要在Page_Load中取出Session 来。原因是:每次点击按钮的时候,Page_Load总是在按钮的Click之前触发。
用户控件里的代码如下
protected void Button1_Click(object sender, EventArgs e) { Session["aaa"] = TextBox1.Text; }
页面代码如下
protected override void OnLoadComplete(EventArgs e) { base.OnLoadComplete(e); if (Session["aaa"] != null) { Label1.Text = Session["aaa"].ToString(); } }
II,使用代理(委托)delegate向页面传值
使用步骤:
第一步:使用delegate关键词定义一个新的代理类型。
public delegate 代理的返回类型 代理名(参数列表);
public delete void ShowDelegate(string s);
第二步:使用上面的代理类型来定义代理变量。
private ShowDelegate Show;
第三步:在页面中指定一个函数,把这个函数赋给代理变量Show
void Haha(string aaa)
{
Console.WriteLine(aaa);
}
Show = new ShowDelegate(Haha); 或Show+=Haha;
第四步:使用代理调用指向的函数
Show("Hello");
案例:在用户控件中点击按钮将文本框的值传到页面的label中去
用户控件代码如下:
public delegate void ShowDelegate(string s); public ShowDelegate Show; protected void Button1_Click(object sender, EventArgs e) { if (Show != null) { Show(TextBox1.Text); } }
页面代码如下:
protected void Page_Load(object sender, EventArgs e) { //TestUC1.Show = new TestUC.ShowDelegate(SetLabelValue); TestUC1.Show += SetLabelValue; } public void SetLabelValue(string s) { Label1.Text = s; }
2.路径(必须在同一级别目录下)
(1)标签/控件(不是从工具箱里拖出来的控件,是自己手写的HTML标签)的路径——只需在其标签内加上runat=server标记即可(注:此时必须再加上id=“xxx”)
(2)样式表的路径——使用外部样式表(样式表的目录和图片目录是固定的,无论页面和用户控件在哪个目录下都不影响样式表中的路径)
(3)外部脚本文件的路径——使用ResolveClientUrl()来动态转换路径
(4)C#代码路径问题——Response. Redirect("~/路径"):按目录从上到下的顺序找
<script src="<%=ResolveClientUrl("Script/JavaScript.js")%>"></script> //括号内为JS脚本代码路径
3.命名——任何带有runat=server的标签/控件,放到用户控件中后,在生成的HTML中,它的ID和Name都会发生一些变化。
Web标准控件的ID,ClientID,UniqueID区别?
ID - 设计时候的控件的ID。控件的这个对象的变量名。
ClientID - 运行呈现为HTML后的ID名。
UniqueID - 运行呈现为HTML后的Name名。
如何在JS中获得它们生成出来的HTML中的ID
var t = document.getElementById("<%= TextBox1.ClientID %>");
案例1:新闻分类显示
1.造用户控件,将每种类型的新闻都造成一个用户控件(此处只造一个用户控件即可,在其中利用添加属性的方法。给其设置不同的新闻类型来控制其显示不同的内容)
public partial class NewsUC : System.Web.UI.UserControl { private string _NewsType; public string NewsType { set { _NewsType = value; } } private string _BgColor; public string Bgcolor { get { return _BgColor; } set { _BgColor = value; } } private NewsDBDataContext context = new NewsDBDataContext(); protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { var q1 = context.News.Where(p=>p.type==_NewsType); Repeater1.DataSource = q1; Repeater1.DataBind(); } } }
2.在用户控件中设计界面,使用Repeater
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="NewsUC.ascx.cs" Inherits="NewsUC" %> <div style="background-color:<%=Bgcolor%>;"> <asp:Repeater ID="Repeater1" runat="server"> <ItemTemplate> <div style="margin-bottom:10px;font-size:12px;"> <span><%#Eval("title") %></span>(<span><%#Eval("time","{0:yyyy.MM.dd}") %></span>) </div> </ItemTemplate> </asp:Repeater> </div>
3.造主页面,显示不同类型的新闻,并给其加上事先设置好的属性
<body> <form id="form1" runat="server"> 国内新闻:<br /> <br /> <uc1:NewsUC ID="NewsUC1" runat="server" NewsType="0" Bgcolor="#FFFFaa" /> <p> 国际新闻</p> <uc1:NewsUC ID="NewsUC2" runat="server" NewsType="1" Bgcolor="#aaFFFF" /> <p> 娱乐新闻</p> <uc1:NewsUC ID="NewsUC3" runat="server" NewsType="2" Bgcolor="#FFaaFF" /> <p> 财经新闻</p> <uc1:NewsUC ID="NewsUC4" runat="server" NewsType="3" Bgcolor="#aaFFaa" /> </form> </body>
案例2:显示汽车图片列表及简介
I,不用用户控件直接拖Repeater的做法
<title></title> <style type="text/css"> .cars { float:left; margin:10px; } </style> </head> <body> <form id="form1" runat="server"> <div> <asp:Repeater ID="Repeater1" runat="server"> <ItemTemplate> <div class="cars"> <img src="images/car/<%#Eval("Pic") %>" /> <div><%#Eval("Name") %></div> </div> </ItemTemplate> </asp:Repeater> </div> </form> </body>
II,使用用户控件,并控制每次显示的个数(直接将上述代码中Repeater及其中的代码复制到用户控件中,并将其拖到页面中)在页面中定义一个属性用来控制显示个数
public partial class Default4 : System.Web.UI.Page { private string _MaxCount="-1"; public string MaxCount { get { return _MaxCount; } set { _MaxCount = value; } } protected void Page_Load(object sender, EventArgs e) { NewsDBDataContext context = new NewsDBDataContext(); if (!IsPostBack) { if (_MaxCount == "-1") { var q1 = context.Car; Repeater1.DataSource = q1; Repeater1.DataBind(); } else { var q1 = context.Car.take(Convert.ToInt32(_MaxCount)); Repeater1.DataSource = q1; Repeater1.DataBind(); } } } }
在页面的源代码中设置用户控件的MaxCount属性,设置成不同的值显示不同的个数
附:用户控件整体只是框架图