當 GridView 欄位數量、顯示/隱藏需在執行期依設定決定時,無法使用靜態 <asp:BoundField>。解決方案是建立實作 ITemplate 的動態欄位類別,在 InstantiateIn 中掛載 DataBinding 事件,於 OnDataBinding 中依資料列內容動態決定輸出(如勾選符號、格式化文字、控制項顯示/隱藏)。
using System.Web.UI;
using System.Web.UI.WebControls;
public class DynamicColumn : ITemplate
{
private readonly string _dataField; // 資料來源欄位名
private readonly int _matchValue; // 比對值
public DynamicColumn(string dataField, int matchValue)
{
_dataField = dataField;
_matchValue = matchValue;
}
public void InstantiateIn(Control container)
{
var lbl = new Label();
lbl.DataBinding += OnDataBinding; // 關鍵:掛載 DataBinding 事件
container.Controls.Add(lbl);
}
private void OnDataBinding(object sender, EventArgs e)
{
var lbl = (Label)sender;
var row = (DataGridItem)lbl.NamingContainer; // GridView 用 GridViewRow
var dataItem = (DataRowView)row.DataItem;
int cellValue = int.Parse(dataItem[_dataField].ToString());
lbl.Text = (cellValue == _matchValue) ? "✓" : "";
}
}
// 程式碼後置 Page_Load 或 GridView PreRender
if (!IsPostBack)
{
// 假設從設定檔讀取要顯示的欄位
var columnsConfig = new[] { new { Field = "Status", Match = 1 }, new { Field = "IsActive", Match = 1 } };
foreach (var cfg in columnsConfig)
{
var templateField = new TemplateField
{
HeaderText = cfg.Field,
ItemTemplate = new DynamicColumn(cfg.Field, cfg.Match)
};
GridView1.Columns.Add(templateField);
}
GridView1.DataSource = GetData(); // DataTable/List
GridView1.DataBind();
}
| 概念 | 說明 |
|---|---|
ITemplate.InstantiateIn | ASP.NET 執行期為每個資料列建立控制項樹的進入點,此處 new Label() 並掛載事件。 |
DataBinding 事件 | 在 DataBind() 過程中,每個資料列繫結前觸發,NamingContainer 即為該列的 DataGridItem/GridViewRow。 |
DataRowView | 資料來源為 DataTable 時,每列包裝為 DataRowView,可用欄位名存取值。 |
TemplateField | GridView 專用欄位類型,接受 ITemplate 作為 ItemTemplate/EditTemplate 等。 |
InstantiateIn 可 new CheckBox、DropDownList、Image、HyperLink 等,視需求輸出。OnDataBinding 中設定 Control.Visible = false。IEditableTemplate 或手動處理 RowUpdating 取值。RowDataBound 直接操作 e.Row.Cells[i].Controls。掌握 ITemplate + DataBinding 模式,讓 GridView 欄位真正實現「執行期完全可配置」。