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

除了 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 方法加载用户控件:

<script language="JavaScript" type="text/javascript"> function doClick(index, numTabs, id) { document.all("tab" + id, index).className = "tab"; for (var i=1; i < numTabs; i++) { document.all("tab" + id, (index + i) % numTabs).className = "backtab"; } document.all("code" + id, index).style.display = ""; for (var j=1; j < numTabs; j++) { document.all("code" + id, (index + j) % numTabs).style.display = "none"; } } </script>
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 窗体页使用。 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值