FormView 是 ASP.NET 2.0 新增的單筆資料呈現控制項,與 DetailsView 同樣顯示單一記錄,但採用完全模板化架構,給予開發者最大彈性控制版面配置、控制項選擇與繫結邏輯。
FormView vs DetailsView 核心差異
| 特性 | FormView | DetailsView |
| 版面定義 | 開發者自訂模板(HTML + 控制項) | 自動產生資料列(Fields 集合) |
| 彈性度 | 極高,任意排版 | 中等,表格式固定 |
| 設計工具支援 | 模板編輯模式 | 智慧標記編輯欄位 |
| 適用場景 | 複雜表單、非表格式呈現、高度客製化 | 快速資料檢視、標準主從表單 |
五大核心模板
| 模板 | 用途 | 典型內容 |
ItemTemplate | 唯讀檢視模式 | Label、Literal、格式化輸出 Eval("Field", "{0:C}") |
EditItemTemplate | 編輯現有記錄 | TextBox、DropDownList、CheckBox、驗證控制項、Bind("Field") |
InsertItemTemplate | 新增記錄 | 輸入控制項、預設值設定、Bind("Field") |
HeaderTemplate | 表單標題區 | 標題文字、圖示、導航連結 |
FooterTemplate | 表單底部區 | 操作按鈕、分頁導航、版權資訊 |
關鍵屬性
DataSourceID:繫結資料源控制項 ID(如 SqlDataSource)。
DataKeyNames:主鍵欄位名稱(支援複合鍵),用於更新/刪除定位。
DefaultMode:ReadOnly(預設)、Edit、Insert。
AllowPaging:啟用分頁導航(需資料源支援)。
EmptyDataText:無資料時顯示文字。
完整範例:Northwind 員工管理表單
<asp:SqlDataSource ID="sdsEmployees" runat="server"
ConnectionString="<%$ ConnectionStrings:NWConnectionString %>"
SelectCommand="SELECT EmployeeID, LastName, FirstName, Title, HireDate, HomePhone FROM Employees"
UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName, Title=@Title, HireDate=@HireDate, HomePhone=@HomePhone WHERE EmployeeID=@EmployeeID"
InsertCommand="INSERT INTO Employees (LastName, FirstName, Title, HireDate, HomePhone) VALUES (@LastName, @FirstName, @Title, @HireDate, @HomePhone)"
DeleteCommand="DELETE FROM Employees WHERE EmployeeID=@EmployeeID">
<UpdateParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="Title" Type="String" />
<asp:Parameter Name="HireDate" Type="DateTime" />
<asp:Parameter Name="HomePhone" Type="String" />
<asp:Parameter Name="EmployeeID" Type="Int32" />
</UpdateParameters>
<InsertParameters>
<asp:Parameter Name="LastName" Type="String" />
<asp:Parameter Name="FirstName" Type="String" />
<asp:Parameter Name="Title" Type="String" />
<asp:Parameter Name="HireDate" Type="DateTime" />
<asp:Parameter Name="HomePhone" Type="String" />
</InsertParameters>
</asp:SqlDataSource>
<asp:FormView ID="FormView1" runat="server" DataSourceID="sdsEmployees"
DataKeyNames="EmployeeID" AllowPaging="True" DefaultMode="ReadOnly">
<HeaderTemplate>
<h3>員工資料管理</h3>
</HeaderTemplate>
<ItemTemplate>
<table class="form-table">
<tr><th>姓氏</th><td><%# Eval("LastName") %></td></tr>
<tr><th>名字</th><td><%# Eval("FirstName") %></td></tr>
<tr><th>職稱</th><td><%# Eval("Title") %></td></tr>
<tr><th>到職日期</th><td><%# Eval("HireDate", "{0:yyyy-MM-dd}") %></td></tr>
<tr><th>家用電話</th><td><%# Eval("HomePhone") %></td></tr>
</table>
<asp:Button CommandName="Edit" Text="編輯" runat="server" />
<asp:Button CommandName="New" Text="新增" runat="server" />
<asp:Button CommandName="Delete" Text="刪除" runat="server" OnClientClick="return confirm('確定刪除?');" />
</ItemTemplate>
<EditItemTemplate>
<table class="form-table">
<tr><th>姓氏</th><td><asp:TextBox ID="txtLastName" runat="server" Text='<%# Bind("LastName") %>' /></td></tr>
<tr><th>名字</th><td><asp:TextBox ID="txtFirstName" runat="server" Text='<%# Bind("FirstName") %>' /></td></tr>
<tr><th>職稱</th><td><asp:TextBox ID="txtTitle" runat="server" Text='<%# Bind("Title") %>' /></td></tr>
<tr><th>到職日期</th><td><asp:TextBox ID="txtHireDate" runat="server" Text='<%# Bind("HireDate", "{0:yyyy-MM-dd}") %>' /></td></tr>
<tr><th>家用電話</th><td><asp:TextBox ID="txtHomePhone" runat="server" Text='<%# Bind("HomePhone") %>' /></td></tr>
</table>
<asp:Button CommandName="Update" Text="儲存" runat="server" />
<asp:Button CommandName="Cancel" Text="取消" runat="server" />
</EditItemTemplate>
<InsertItemTemplate>
<table class="form-table">
<tr><th>姓氏</th><td><asp:TextBox ID="txtLastName" runat="server" Text='<%# Bind("LastName") %>' /></td></tr>
<tr><th>名字</th><td><asp:TextBox ID="txtFirstName" runat="server" Text='<%# Bind("FirstName") %>' /></td></tr>
<tr><th>職稱</th><td><asp:TextBox ID="txtTitle" runat="server" Text='<%# Bind("Title") %>' /></td></tr>
<tr><th>到職日期</th><td><asp:TextBox ID="txtHireDate" runat="server" Text='<%# Bind("HireDate") %>' /></td></tr>
<tr><th>家用電話</th><td><asp:TextBox ID="txtHomePhone" runat="server" Text='<%# Bind("HomePhone") %>' /></td></tr>
</table>
<asp:Button CommandName="Insert" Text="新增" runat="server" />
<asp:Button CommandName="Cancel" Text="取消" runat="server" />
</InsertItemTemplate>
<FooterTemplate>
<asp:Button CommandName="Page" CommandArgument="Prev" Text="上一筆" runat="server" />
<asp:Button CommandName="Page" CommandArgument="Next" Text="下一筆" runat="server" />
</FooterTemplate>
</asp:FormView>
CommandName 標準動作對照
| CommandName | 動作 | 觸發模板切換 |
Edit | 進入編輯模式 | ItemTemplate → EditItemTemplate |
New | 進入新增模式 | ItemTemplate → InsertItemTemplate |
Update | 儲存編輯 | 執行 UpdateCommand → ItemTemplate |
Insert | 儲存新增 | 執行 InsertCommand → ItemTemplate |
Delete | 刪除記錄 | 執行 DeleteCommand → ItemTemplate |
Cancel | 取消編輯/新增 | 回 ItemTemplate |
Page | 分頁導航 | CommandArgument: Prev/Next |
雙向繫結 Bind() 關鍵點
Bind("FieldName"):僅支援於 EditItemTemplate、InsertItemTemplate 輸入控制項屬性(Text、SelectedValue、Checked)。
- 自動收集表單值建立參數集合傳遞給資料源
Update/InsertCommand。
- 格式化字串:
Bind("Field", "{0:yyyy-MM-dd}") 僅支援單向格式化,回寫時需自行處理(或使用 FormatParameter 事件)。
進階:ItemCommand 事件攔截自訂邏輯
protected void FormView1_ItemCommand(object sender, FormViewCommandEventArgs e)
{
if (e.CommandName == "Update")
{
// 額外驗證、日誌記錄、觸發工作流
TextBox txtHireDate = (TextBox)FormView1.FindControl("txtHireDate");
if (DateTime.Parse(txtHireDate.Text) > DateTime.Today)
{
e.Cancel = true; // 取消更新
// 顯示錯誤訊息...
}
}
}
FormView 以模板化架構實現單筆資料表單的極致客製化,是複雜業務表單開發的首選控制項。