ASP.NET 頁面若有上百個 TextBox,每個都掛一個 RequiredFieldValidator,客戶端會渲染上百個 <span>,頁面體積暴增、初始化緩慢。解法:單一 CustomValidator 動態切換驗證目標。
CustomValidator 客戶端物件擁有 controltovalidate、clientvalidationfunction、validateemptytext 等屬性,可在 onfocus 事件中動態修改,指向當前獲得焦點的控制項。
<body>
<form id="form1" runat="server">
<div>
<asp:CustomValidator ID="CustomValidator1" runat="server" />
<asp:ValidationSummary ID="ValidationSummary1" runat="server" />
</div>
</form>
</body>
protected void Page_Load(object sender, EventArgs e) {
if (!IsPostBack) {
for (int i = 0; i < 10; i++) {
TextBox tb = new TextBox();
tb.ID = "tb" + i;
// 關鍵:onfocus 觸發 JS 函式,傳入 this 與 Validator ClientID
tb.Attributes.Add("onfocus",
"HookUpControl(this, '" + CustomValidator1.ClientID + "')");
Page.Form.Controls.Add(tb);
}
}
}
function HookUpControl(curObj, validatorClientID) {
var val = document.getElementById(validatorClientID);
val.controltovalidate = curObj.id; // 切換驗證目標
val.clientvalidationfunction = "validatetextbox"; // 指定驗證函式
val.validateemptytext = "true"; // 空白也驗證
ValidatorHookupControl(curObj, val); // 官方 API 完成掛鉤
}
function validatetextbox(source, args) {
args.IsValid = (args.Value.trim() !== "");
}
onfocus。HookUpControl 將唯一的 CustomValidator 指向該 TextBox。validatetextbox 驗證當前目標。ValidationSummary 收集所有驗證結果顯示。| 優點 | 缺點/限制 |
|---|---|
| 頁面大幅瘦身(驗證控制項從 N 個降為 1 個) | 同一時間只能驗證「目前焦點控制項」;送出表單時需額外邏輯逐一驗證 |
| 客戶端腳本極少,初始化極快 | 無法支援伺服端驗證(OnServerValidate)除非同步切換 |
| 動態產生控制項場景完美適用 | 若需同時顯示多欄位錯誤訊息,需搭配其他機制 |
function validateAll(validatorID) {
var val = document.getElementById(validatorID);
var inputs = document.querySelectorAll('input[type=text]');
var allValid = true;
inputs.forEach(function(tb) {
val.controltovalidate = tb.id;
ValidatorValidate(val); // 手動觸發驗證
if (!val.isvalid) allValid = false;
});
return allValid;
}
// 送出按鈕 OnClientClick="return validateAll('CustomValidator1');"
此技巧在「大量動態欄位、即時單欄驗證、送出前全檢」場景極具價值,是 ASP.NET WebForms 時代的經典優化模式。