首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ASP.NET Web Forms 註冊與使用使用者控件 (.ascx) 完整教學

     編輯:ASP.NET 基礎

使用者控件 vs 自訂控件 vs Server Control

類型副檔名建立方式重用層級適用場景
使用者控件 .ascx 設計師拖拉 + 程式碼後置,類似迷你頁面 專案內共用 頁面區塊重用 (Header、Footer、選單、搜尋列、分頁器)
自訂控件 .cs (類別庫) 繼承 Control/WebControl,完整渲染控制 跨專案、NuGet 套件 複雜互動元件 (Grid、Tree、圖表)、第三方元件庫
Server Control (內建) - GridView、Repeater、DropDownList... - 標準資料綁定、表單輸入

三步驟建立與引用使用者控件

步驟 1:新增 .ascx 檔案 (Visual Studio: 右鍵專案 → Add → New Item → Web User Control)

Header.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Header.ascx.cs" Inherits="Demo.Controls.Header" %>
<!-- 無需 html/head/body/form 標籤 -->
<header class="site-header">
    <div class="container">
        <h1><asp:Literal ID="litSiteTitle" runat="server" /></h1>
        <nav>
            <asp:HyperLink ID="hlHome" runat="server" Text="首頁" NavigateUrl="~/" /> |
            <asp:HyperLink ID="hlAbout" runat="server" Text="關於我們" NavigateUrl="~/About.aspx" /> |
            <asp:HyperLink ID="hlContact" runat="server" Text="聯絡我們" NavigateUrl="~/Contact.aspx" />
        </nav>
    </div>
</header>
<style>
    .site-header { background: #343a40; color: white; padding: 1rem 0; }
    .site-header a { color: #adb5bd; text-decoration: none; margin: 0 0.5rem; }
    .site-header a:hover { color: white; }
</style>

Header.ascx.cs

using System;
using System.Web.UI;

namespace Demo.Controls
{
    public partial class Header : System.Web.UI.UserControl
    {
        // 公開屬性:允許父頁面設定標題
        public string SiteTitle
        {
            get => litSiteTitle.Text;
            set => litSiteTitle.Text = value;
        }

        // 公開方法:動態切換導航狀態
        public void SetActiveNav(string navId)
        {
            // 實作:依 navId 找對應 HyperLink 加上 CSS class
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                // 預設值
                if (string.IsNullOrEmpty(litSiteTitle.Text))
                    litSiteTitle.Text = "我的網站";
            }
        }
    }
}

步驟 2:在 .aspx 頁面或 Master Page 註冊指令

<%@ Page Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Demo.Default" %>

<!-- 註冊控件:Src=相對路徑, TagPrefix=自訂前綴, TagName=標籤名稱 -->
<%@ Register Src="~/Controls/Header.ascx" TagPrefix="uc" TagName="Header" %>
<%@ Register Src="~/Controls/Footer.ascx" TagPrefix="uc" TagName="Footer" %>
<%@ Register Src="~/Controls/SearchBox.ascx" TagPrefix="uc" TagName="SearchBox" %>

步驟 3:在頁面標記中使用控件

<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    <!-- 使用註冊的 TagPrefix:TagName -->
    <uc:Header ID="ucHeader" runat="server" SiteTitle="首頁 - 我的系統" />

    <main class="container">
        <uc:SearchBox ID="ucSearch" runat="server" OnSearch="ucSearch_Search" />
        <h2>歡迎來到首頁</h2>
        <p>這裡是主要內容區...</p>
    </main>

    <uc:Footer ID="ucFooter" runat="server" CompanyName="Demo Corp" />
</asp:Content>

進階:控件間通訊與事件傳遞

1. 父頁面訂閱控件事件

SearchBox.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="SearchBox.ascx.cs" Inherits="Demo.Controls.SearchBox" %>
<div class="search-box">
    <asp:TextBox ID="txtKeyword" runat="server" CssClass="form-control" placeholder="輸入關鍵字..." />
    <asp:Button ID="btnSearch" runat="server" Text="搜尋" CssClass="btn btn-primary" OnClick="btnSearch_Click" />
</div>
public partial class SearchBox : System.Web.UI.UserControl
{
    // 定義事件委派
    public event EventHandler Search;

    // 事件參數類別
    public class SearchEventArgs : EventArgs
    {
        public string Keyword { get; set; }
    }

    protected void btnSearch_Click(object sender, EventArgs e)
    {
        string kw = txtKeyword.Text.Trim();
        // 觸發事件,父頁面處理
        Search?.Invoke(this, new SearchEventArgs { Keyword = kw });
    }

    // 公開屬性:預設關鍵字
    public string DefaultKeyword
    {
        get => txtKeyword.Text;
        set => txtKeyword.Text = value;
    }
}

Default.aspx.cs

protected void ucSearch_Search(object sender, SearchBox.SearchEventArgs e)
{
    // 父頁面接收事件,執行查詢、重導向、綁定 GridView 等
    Response.Redirect($"~/SearchResults.aspx?q={Server.UrlEncode(e.Keyword)}");
}

2. 控件尋找父頁面/其他控件 (FindControl)

// 在控件內取得父頁面上的其他控件
var master = this.Page.Master;
var header = master.FindControl("ucHeader") as Header;
header?.SetActiveNav("home");

// 或在父頁面取得控件實例
var searchBox = FindControl("ucSearch") as SearchBox;
searchBox.DefaultKeyword = "預設關鍵字";

在 Master Page 統一註冊 (全站可用)

Site.Master

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="Demo.SiteMaster" %>
<%@ Register Src="~/Controls/Header.ascx" TagPrefix="uc" TagName="Header" %>
<%@ Register Src="~/Controls/Footer.ascx" TagPrefix="uc" TagName="Footer" %>
<html><body>
    <form id="form1" runat="server">
        <uc:Header ID="ucHeader" runat="server" />
        <asp:ContentPlaceHolder ID="MainContent" runat="server" />
        <uc:Footer ID="ucFooter" runat="server" />
    </form></body></html>

內容頁面**無需重複註冊**,直接使用 `` 即可 (前綴需一致)。

Web.config 全域註冊 (專案層級)

<configuration>
  <system.web>
    <pages>
      <controls>
        <add tagPrefix="uc" tagName="Header" src="~/Controls/Header.ascx" />
        <add tagPrefix="uc" tagName="Footer" src="~/Controls/Footer.ascx" />
        <add tagPrefix="uc" tagName="SearchBox" src="~/Controls/SearchBox.ascx" />
      </controls>
    </pages>
  </system.web>
</configuration>

所有 .aspx 自動可用 ``,無需頁面層級 `@Register`。

常見問題與最佳實務

問題原因解決
控件內控件 ID 衝突 多次引用同一控件,ID 重複 ASP.NET 自動處理 NamingContainer,確保 `ClientIDMode="AutoID"` (預設) 即可
控件事件不觸發 `AutoEventWireup="false"` 或事件綁定錯誤 檢查 `@Control AutoEventWireup="true"`、按鈕 `OnClick` 對應方法名
樣式/Script 重複引用 每個控件都寫 `