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

ASP.NET 實現相似頁面後台代碼抽象與動態 GridView 資料綁定:多型實戰範例

     編輯:關於ASP.NET

ASP.NET 實現相似頁面後台代碼抽象與動態 GridView 資料綁定:多型實戰範例

面對「我的申請」與「待我審批」兩個高度相似頁面:查詢條件、列表顯示、審批歷程完全一致,唯一差異在於「待審批」多一個「執行審批」操作欄,且不同應用/角色顯示欄位不同。利用繼承與多型抽象共同邏輯,配合動態 GridView 欄位實現靈活擴充。

頁面結構

  • MyApprovals.aspx:我的申請列表
  • ToApprovals.aspx:待我審批列表 (含操作欄)
  • 共用母版頁導航選單

基類設計:ApprovalBasePage


public abstract class ApprovalBasePage : BasePage {
    // 子類決定頁面類型:0=我的申請, 1=待審批
    protected virtual int PageType { get { return 0; } }

    private ApprovalData _dataSource;
    protected ApprovalData DataSource {
        get {
            if (_dataSource == null)
                _dataSource = ApprovalData.GetData(this.PageType);
            return _dataSource;
        }
    }

    // 核心資料綁定邏輯 (可被子類覆寫)
    protected virtual void BindData(string key = "") {
        var dt = DataToTable(key);
        if (dt != null) {
            gvApprovals.DataSource = dt;
            gvApprovals.DataBind();
        }
    }

    // 將 ApprovalData 轉為 DataTable 供 GridView 綁定
    protected DataTable DataToTable(string key = "") {
        var dt = new DataTable();
        if (DataSource == null) return null;
        
        // 動態建立欄位
        foreach (var colName in DataSource.HeadList)
            dt.Columns.Add(colName, typeof(string));
        
        // 填充資料
        foreach (var rowData in DataSource.ContentList) {
            var dr = dt.NewRow();
            for (int i = 0; i < rowData.Count && i < dt.Columns.Count; i++)
                dr[i] = rowData[i];
            dt.Rows.Add(dr);
        }
        return dt;
    }

    // 共用事件處理
    protected void Page_Load(object sender, EventArgs e) {
        if (!IsPostBack) BindData();
    }
    protected void btnSearch_Click(object sender, EventArgs e) {
        BindData(txtKey.Text);
    }
}

資料來源模型:ApprovalData


public class ApprovalData {
    public List HeadList { get; set; }      // 欄位標題
    public List> ContentList { get; set; } // 資料列集合
    
    public static ApprovalData GetData(int pageType) {
        // 實際專案中從資料庫/服務取得
        // 此處模擬資料
        var data = new ApprovalData();
        data.HeadList = new List { "流水號", "申請人", "金額", "狀態" };
        if (pageType == 1) data.HeadList.Add("操作"); // 待審批多一欄
        
        data.ContentList = new List> {
            new List { "A001", "張三", "1000", "審核中" },
            new List { "A002", "李四", "2000", "已核准" }
        };
        if (pageType == 1) {
            data.ContentList[0].Add("審批");
            data.ContentList[1].Add("審批");
        }
        return data;
    }
}

子類實作:MyApprovalsPage


public partial class MyApprovals : ApprovalBasePage {
    protected override int PageType { get { return 0; } }
    
    // 可選:覆寫 BindData 增加特定邏輯
    // protected override void BindData(string key = "") { ... }
}

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="MyApprovals.aspx.cs" Inherits="WebApp.MyApprovals" MasterPageFile="~/Site.Master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    <p>
        <asp:TextBox ID="txtKey" runat="server"></asp:TextBox>
        <asp:Button ID="btnSearch" runat="server" Text="查詢" OnClick="btnSearch_Click" />
        <asp:Label ID="lblMsg" runat="server" ForeColor="Red"></asp:Label>
    </p>
    <p>
        <asp:GridView ID="gvApprovals" runat="server" AutoGenerateColumns="true"></asp:GridView>
    </p>
</asp:Content>

子類實作:ToApprovalsPage (擴充操作欄)


public partial class ToApprovals : ApprovalBasePage {
    protected override int PageType { get { return 1; } }
    
    protected override void BindData(string key = "") {
        base.BindData(key); // 先綁定基本資料
        
        // 動態添加操作按鈕欄 (若未自動產生)
        if (gvApprovals.Columns.Count == 0) { // AutoGenerateColumns=false 時
            var btnField = new ButtonField {
                HeaderText = "操作",
                Text = "審批",
                CommandName = "Approve",
                ButtonType = ButtonType.Button
            };
            gvApprovals.Columns.Add(btnField);
        }
    }
    
    protected void gvApprovals_RowCommand(object sender, GridViewCommandEventArgs e) {
        if (e.CommandName == "Approve") {
            int index = Convert.ToInt32(e.CommandArgument);
            // 執行審批邏輯
        }
    }
}

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ToApprovals.aspx.cs" Inherits="WebApp.ToApprovals" MasterPageFile="~/Site.Master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    <p>...查詢區同 MyApprovals...</p>
    <p>
        <asp:GridView ID="gvApprovals" runat="server" AutoGenerateColumns="false" OnRowCommand="gvApprovals_RowCommand">
            <Columns>
                <!-- 動態產生 BoundField 對應 HeadList -->
            </Columns>
        </asp:GridView>
    </p>
</asp:Content>

關鍵設計模式解析

模式應用位置效益
Template MethodBindData 定義演算法骨架,DataToTable 為可變步驟固定流程、允許局部客製化
Factory MethodPageType 屬性決定資料來源型態延遲具體型別建立到子類
動態欄位生成DataToTable 根據 HeadList 建立 DataTable 欄位支援不同應用/角色顯示不同欄位
策略模式 (潛在)若審批邏輯複雜,可抽出 IApprovalStrategy 注入分離演算法、支援運行時切換

現代化改良建議 (ASP.NET Core / MVC)

  • 棄用 Web Forms,改用 ASP.NET Core MVC + Razor 或 Blazor。
  • 資料綁定改用 ViewModel + Tag Helpers,<table> 由 foreach 渲染,完全控制 HTML。
  • 共用邏輯抽至 Service Layer,控制器薄而精簡。
  • 動態欄位透過 ViewBag.Columns 或 IColumnProvider 服務配置。
  • GridView 替代方案:DataTables.js、AG Grid、MudBlazor DataGrid 等前端元件,支援排序、分頁、匯出、編輯。

總結

透過基類封裝共同邏輯 (查詢、綁定、資料轉換)、虛擬屬性/方法實現多型差異 (頁面類型、操作欄)、動態 DataTable 適配 GridView,成功消除重複代碼,支援欄位動態配置。此範例展示經典 ASP.NET Web Forms 時代的物件導向設計精髓,現代開發應遷移至 MVC/Core 架構並採用前端元件庫。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved