用户控件的一些常用方法和注意事项

来源:互联网 发布:马蓉这种女人多吗 知乎 编辑:程序博客网 时间:2024/04/30 08:31
除了 ASP.NET 提供的内置服务器控件之外,还可以使用已学会的编写 Web 窗体页的相同编程技巧轻松地定义自己的控件。实际上,只需少量修改,几乎任何 Web 窗体页都可在其他页中作为服务器控件重用(注意,用户控件的类型是 System.Web.UI.TemplateParser,该类型直接从 System.Web.UI.UserControl 继承)。用作服务器控件的 Web 窗体页简称为用户控件。作为约定,使用 .ascx 扩展名指示这样的控件。这样可以确保用户控件的文件不能作为独立的 Web 窗体页执行(您会略微了解到在用户控件和 Web 窗体页之间有很少但很重要的差异)。用户控件通过 Register 指令包含在 Web 窗体页中。
<%@ Register TagPrefix="Acme" TagName="Message" Src="pagelet1.ascx" %>
TagPrefix 确定用户控件的唯一命名空间(以便多个同名的用户控件可以相互区分)。TagName 是用户控件的唯一名称(可以选择任何名称)。Src 属性是用户控件的虚拟路径 -- 如“MyPagelet.ascx”或“/MyApp/Include/MyPagelet.ascx”。注册了用户控件后,可以像放置普通的服务器控件那样,将用户控件标记放置在 Web 窗体页中(包括 runat="server" 属性):

<Acme:Message runat="server"/>
下面的示例演示导入到另一 Web 窗体页中的用户控件。注意,本例中的用户控件只是一个简单的静态文件。

C# UserCtrl1.aspx
Run Sample View Source

公开用户控件属性

当 Web 窗体页被视为控件时,该 Web 窗体的公共字段和方法也被提升为该控件的公共属性 (Property) (即标记属性 (Attribute))和方法。下面的示例显示前一用户控件示例的扩展,添加了两个公共 String 字段。注意,这些字段可以在包含页中以声明方式或编程方式设置。

C# UserCtrl2.aspx
Run Sample View Source
<%@ Register TagPrefix="Acme" TagName="Message" Src="userctrl2_cs.ascx" %><html>  <script language="C#" runat="server">      void SubmitBtn_Click(Object sender, EventArgs E) {          MyMessage.Text = "Message text changed!";          MyMessage.Color = "red";      }  </script><body style="font: 10pt verdana">  <h3>A Simple User Control w/ Properties</h3>  <form runat="server">    <Acme:Message id="MyMessage" Text="This is a custom message!" Color="blue" runat="server"/>    <p>    <asp:button text="Change Properties" OnClick="SubmitBtn_Click" runat=server/>  </form></body></html>用户控件代码:
<script language="C#" runat="server">  public String Color = "blue";  public String Text = "This is a simple message user control!";</script><span id="Message" style="color:<%=Color%>"><%=Text%></span>

除了将公共字段提升为控件属性外,还可以使用属性语法。属性语法具有能够在设置或检索属性时执行代码的优点。下面的示例演示 Address 用户控件,该控件在内部包装了 TextBox 控件的文本属性。这样做的好处在于控件可以无偿继承 TextBox 控件的自动状态管理。

注意,在包含 Web 窗体页上有两个 Address 用户控件,它们的 Caption 属性分别设置为“Billing Address”和“Shipping Address”。用户控件的真正威力在于这种可重用性。

C# UserCtrl3.aspx
Run Sample View Source
<%@ Register TagPrefix="Acme" TagName="Address" Src="userctrl3_cs.ascx" %><html>    <script language="C#" runat="server">        void SubmitBtn_Click(Object sender, EventArgs E) {                    MyLabel.Text += "<b>Shipping Address:</b> "                         +   ShipAddr.Address + ", "                          +   ShipAddr.City + ", "                          +   ShipAddr.State + ", "                          +   ShipAddr.Zip + "<br>";            MyLabel.Text += "<b>Billing Address:</b> "                         +   BillAddr.Address + ", "                          +   BillAddr.City + ", "                          +   BillAddr.State + ", "                          +   BillAddr.Zip + "<br>";        }    </script><body style="font: 10pt verdana">  <h3>A Simple User Control w/ Properties</h3>  <form runat="server">    <Acme:Address id="ShipAddr" Caption="Shipping Address" Address="One Microsoft Way" City="Redmond" State="WA" Zip="98052" runat="server"/>    <p>    <Acme:Address id="BillAddr" Caption="Billing Address" runat="server"/>    <p>    <asp:button Text="Submit Form" OnClick="SubmitBtn_Click" runat=server/>  </form>  <asp:Label id="MyLabel" runat="server"/></body></html>用户控件代码:
<script language="C#" runat="server">  public String Caption = "Address";  public String Address {    get {      return TxtAddress.Value;    }    set {      TxtAddress.Value = value;    }  }  public String City {    get {      return TxtCity.Value;    }    set {      TxtCity.Value = value;    }  }  public String State {    get {      return TxtState.Value;    }    set {      TxtState.Value = value;    }  }  public String Zip {    get {      return TxtZip.Value;    }    set {      TxtZip.Value = value;    }  }</script><table style="font: 10pt verdana">  <tr>    <td colspan="6" style="padding-bottom:10">      <b><%=Caption%></b>    </td>  </tr>  <tr>    <td>      Address:     </td>    <td colspan="5">      <input id="TxtAddress" size="50" type="text" runat="server">    </td>  </tr>  <tr>    <td>      City:     </td>    <td>      <input id="TxtCity" type="text" runat="server">    </td>    <td>      State:     </td>    <td>      <input id="TxtState" size="2" type="text" runat="server">    </td>    <td>      Zip:     </td>    <td>      <input id="TxtZip" size="5" type="text" runat="server">    </td>  </tr></table>

另一个有用的用户控件是用于收集用户名和密码的 Login 控件。

C# UserCtrl4.aspx
Run Sample View Source
<%@ Register TagPrefix="Acme" TagName="Login" Src="userctrl4_cs.ascx" %><html><script language="C#" runat="server">  void Page_Load(Object sender, EventArgs E) {    if (Page.IsPostBack) {      MyLabel.Text += "The UserId is " + MyLogin.UserId + "<br>";      MyLabel.Text += "The Password is " + MyLogin.Password + "<br>";    }      }</script><body style="font: 10pt verdana">  <h3>A Login User Control</h3>  <form runat="server">    <Acme:Login id="MyLogin" UserId="John Doe" Password="Secret" BackColor="beige" runat="server"/>  </form>  <asp:Label id="MyLabel" runat="server"/></body></html>用户控件代码:
<script language="C#" runat="server">  public String BackColor = "white";  public String UserId {    get {      return User.Text;    }    set {      User.Text = value;    }  }  public String Password {    get {      return Pass.Text;    }    set {      Pass.Text = value;    }  }</script><table style="background-color:<%=BackColor%>;font: 10pt verdana;border-width:1;border-style:solid;border-color:black;" cellspacing=15>  <tr>    <td><b>Login: </b></td>    <td><ASP:TextBox id="User" runat="server"/></td>  </tr>  <tr>    <td><b>Password: </b></td>    <td><ASP:TextBox id="Pass" TextMode="Password" runat="server"/></td>  </tr>  <tr>    <td></td>    <td><ASP:Button Text="Submit" runat="server"/></td>  </tr></table>

在本示例中,窗体验证控件被添加到 Login 用户控件。

C# UserCtrl5.aspx
Run Sample View Source
<%@ Register TagPrefix="Acme" TagName="Login" Src="userctrl5_cs.ascx" %><html><script language="C#" runat="server">  public void Page_Load(Object sender, EventArgs E) {    if (Page.IsPostBack) {        Page.Validate();        if (Page.IsValid) {            MyLabel.Text += "The UserId is " + MyLogin.UserId + "<br>";            MyLabel.Text += "The Password is " + MyLogin.Password + "<br>";        }    }  }</script><body style="font: 10pt verdana">  <h3>A Login User Control</h3>  <form runat="server">    <Acme:Login id="MyLogin" BackColor="beige" runat="server"/>  </form>  <asp:Label id="MyLabel" runat="server"/></body></html>用户控件代码:
    get {      return Page.IsValid;    }  }</script><table style="background-color:<%=BackColor%>;font: 10pt verdana;border-width:1;border-style:solid;border-color:black;" cellspacing=15>  <tr>    <td><b>Login: </b></td>    <td><ASP:TextBox id="User" runat="server"/></td>  </tr>  <tr>    <td><b>Password: </b></td>    <td><ASP:TextBox id="Pass" TextMode="Password" runat="server"/></td>  </tr>  <tr>    <td></td>    <td><ASP:Button Text="Submit" runat="server"/></td>  </tr>  <tr>    <td align="center" valign="top" colspan="2">          <asp:RegularExpressionValidator id="Validator1"          ControlToValidate="Pass"          ValidationExpression="[0-9a-zA-Z]{5,}"          Display="Dynamic"          Font-Size="8pt"          runat=server>          Password must be >= 5 alphanum chars<br>      </asp:RegularExpressionValidator>            <asp:RequiredFieldValidator id="Validator2"          ControlToValidate="User"          Font-Size="8pt"          Display="Dynamic"          runat=server>          UserId cannot be blank<br>      </asp:RequiredFieldValidator>            <asp:RequiredFieldValidator id="Validator3"          ControlToValidate="Pass"          Font-Size="8pt"          Display="Dynamic"          runat=server>          Password cannot be blank<br>      </asp:RequiredFieldValidator>          </td>  </tr></table>

在用户控件中封装事件

用户控件参与请求的整个执行生存期,方式与普通的服务器控件类似。这意味着用户控件可以处理自己的事件,封装来自包含 Web 窗体页的某些页逻辑。下面的示例演示一个在内部处理自己的回发的产品清单用户控件。请注意,该用户控件本身没有包装 <form runat="server"> 控件。由于一页上只能有一个窗体控件(ASP.NET 不允许嵌套的服务器窗体),因此需要包含 Web 窗体页负责定义该控件。

C# UserCtrl6.aspx
Run Sample View Source
<%@ Page Language="C#" %><%@ Register TagPrefix="Acme" TagName="BookList" Src="userctrl6_cs.ascx" %><html><body style="font: 10pt verdana">  <h3>A User Control w/ an Event</h3>  <form runat="server">    <Acme:BookList runat="server" id="BookList1" />  </form></body></html>用户控件代码:
<%@ Import Namespace="System.Data" %><%@ Import Namespace="System.Data.SqlClient" %><script language="C#" runat="server">    void Page_Load(Object Src, EventArgs e) {        if (!Page.IsPostBack) {          SqlConnection myConnection = new SqlConnection("server=(local)//SQLExpress;database=pubs;Integrated Security=SSPI");          SqlDataAdapter myCommand = new SqlDataAdapter("select * from Titles where type='" + Category.SelectedItem.Value + "'", myConnection);          DataSet ds = new DataSet();          myCommand.Fill(ds, "Titles");          MyDataList.DataSource = ds.Tables["Titles"].DefaultView;          MyDataList.DataBind();       }    }    void Category_Select(Object sender, EventArgs e) {      SqlConnection myConnection = new SqlConnection("server=(local)//SQLExpress;database=pubs;Integrated Security=SSPI");      SqlDataAdapter myCommand = new SqlDataAdapter("select * from Titles where type='" + Category.SelectedItem.Value + "'", myConnection);      DataSet ds = new DataSet();      myCommand.Fill(ds, "Titles");      MyDataList.DataSource = ds.Tables["Titles"].DefaultView;      MyDataList.DataBind();    }</script><table style="font: 10pt verdana">  <tr>    <td><b>Select a Category:</b></td>    <td style="padding-left:15">      <ASP:DropDownList AutoPostBack="true" id="Category" OnSelectedIndexChanged="Category_Select" runat="server">        <ASP:ListItem value="business">Business</ASP:ListItem>        <ASP:ListItem value="trad_cook">Traditional Cooking</ASP:ListItem>        <ASP:ListItem value="mod_cook">Modern Cooking</ASP:ListItem>      </ASP:DropDownList>    </td>  </tr></table><ASP:DataList id="MyDataList" BorderWidth="0" RepeatColumns="2" runat="server">    <ItemTemplate>      <table cellpadding=10 style="font: 10pt verdana">        <tr>          <td valign="top">            <img align="top" src='<%# DataBinder.Eval(Container.DataItem, "title_id", "images/title-{0}.gif") %>' >          </td>          <td valign="top">            <b>Title: </b><%# DataBinder.Eval(Container.DataItem, "title") %><br>            <b>Category: </b><%# DataBinder.Eval(Container.DataItem, "type") %><br>            <b>Publisher ID: </b><%# DataBinder.Eval(Container.DataItem, "pub_id") %><br>            <b>Price: </b><%# DataBinder.Eval(Container.DataItem, "price", "$ {0}") %>          </td>        </tr>      </table>    </ItemTemplate></ASP:DataList>

以编程方式创建用户控件

与普通服务器控件一样,用户控件也可以以编程方式创建。通过传入用户控件源文件的虚拟路径,可使用页的 LoadControl 方法加载用户控件:

td.code { padding-left:10px; padding-right:10px; padding-top:0px; padding-bottom:0px; border-left: 1px solid #B1B1B1; border-bottom: 1px solid #DADADA; border-top: none; border-right: 1px solid #DADADA; } td.tab { text-align:center; font: verdana; width:15%; border-top: 1px solid #B1B1B1; border-bottom: none; border-left: 1px solid #B1B1B1; border-left: 1px solid #B1B1B1; cursor: hand; background: #F0F0F0; padding: 3px; } td.backtab { text-align: center; font: verdana; width: 15%; border-top: 1px solid #B1B1B1; border-right: none; border-bottom: 1px solid #B1B1B1; border-left: 1px solid #B1B1B1; cursor: hand; background: #E3E3E3; padding: 3px; } td.space { width:70%; font: x-small verdana; padding: 0px 0px 0px 0px; border-top: none; border-right: none; border-bottom: 1px solid #B1B1B1; border-left: 1px solid #B1B1B1; background: white; } C# VB  
Control c1 = LoadControl("userctrl7.ascx");((UserCtrl7)c1).Category = "business";Page.Controls.Add(c1);

用户控件的类型由 Control 指令的 ClassName 属性确定。例如,以文件名“userctrl7.ascx”保存的用户控件被指定为强类型“UserCtrl7”,如下所示:
<%@ Control ClassName="UserCtrl7" %>
由于 LoadControl 方法返回 System.Web.UI.Control 类型,因此必须将其转换为适当的强类型以便设置控件的各个属性。最后,用户控件被添加到基页的 ControlCollection

C# UserCtrl7.aspx
Run Sample View Source
<%@ Register TagPrefix="Acme" TagName="BookList" Src="userctrl7_cs.ascx" %><html>    <script language="C#" runat="server">        void Page_Load(Object sender, EventArgs E) {            Page.Controls.Add(new HtmlGenericControl("hr"));            Control c1 = LoadControl("userctrl7_cs.ascx");            ((UserCtrl7CS)c1).Category = "business";            Page.Controls.Add(c1);            Page.Controls.Add(new HtmlGenericControl("hr"));            Control c2 = LoadControl("userctrl7_cs.ascx");            ((UserCtrl7CS)c2).Category = "trad_cook";            Page.Controls.Add(c2);            Page.Controls.Add(new HtmlGenericControl("hr"));            Control c3 = LoadControl("userctrl7_cs.ascx");            ((UserCtrl7CS)c3).Category = "mod_cook";            Page.Controls.Add(c3);        }    </script><body style="font: 10pt verdana">  <h3>Creating User Controls Programmatically</h3></body></html>用户控件代码:
<%@ Control ClassName="UserCtrl7CS" %><%@ Import Namespace="System.Data" %><%@ Import Namespace="System.Data.SqlClient" %><script language="C#" runat="server">    private String _category = "";    public String Category {      get {        return _category;      }      set {          _category = value;          SqlConnection myConnection = new SqlConnection("server=(local)//SQLExpress;database=pubs;Integrated Security=SSPI");          SqlDataAdapter myCommand = new SqlDataAdapter("select * from Titles where type='" + _category + "'", myConnection);          DataSet ds = new DataSet();          myCommand.Fill(ds, "Titles");          MyDataList.DataSource = ds.Tables["Titles"].DefaultView;          MyDataList.DataBind();      }    }</script><span style="font: 12pt verdana">Category: <%=Category%></span><ASP:DataList id="MyDataList" BorderWidth="0" RepeatColumns="2" runat="server">    <ItemTemplate>      <table cellpadding=10 style="font: 10pt verdana">        <tr>          <td valign="top">            <img align="top" src='<%# DataBinder.Eval(Container.DataItem, "title_id", "images/title-{0}.gif") %>' >          </td>          <td valign="top">            <b>Title: </b><%# DataBinder.Eval(Container.DataItem, "title") %><br>            <b>Category: </b><%# DataBinder.Eval(Container.DataItem, "type") %><br>            <b>Publisher ID: </b><%# DataBinder.Eval(Container.DataItem, "pub_id") %><br>            <b>Price: </b><%# DataBinder.Eval(Container.DataItem, "price", "$ {0}") %>          </td>        </tr>      </table>    </ItemTemplate></ASP:DataList>

重要事项 仅当用户控件包含 Register 指令时(即使没有实际声明任何用户控件标记),用户控件的强类型才能由包含 Web 窗体页使用。 
 
原创粉丝点击