需求描述
對錶單內的所有欄位進行操作也是常見需求,這些操作有:
- 禁用:表單欄位變灰,不響應使用者動作。
- 只讀:表單欄位不變灰,但不接受使用者輸入(實際上是設定DOM節點的readonly屬性),有觸發器的要隱藏起來
- 設定無效標識:一般用在伺服器端驗證失敗的提示資訊
介面效果
前臺程式碼
前臺程式碼非常直觀,只是一個Form控制元件外加幾個Button控制元件,按鈕的響應事件在後臺完成:
1 <f:PageManager ID="PageManager1" runat="server" /> 2 <f:Form Width="600px" LabelWidth="100px" OffsetRight="10px" LabelSeparator=":" 3 BodyPadding="5px" EnableCollapse="true" ID="Form1" runat="server" Title="表單"> 4 <Rows> 5 <f:FormRow> 6 <Items> 7 <f:Label ID="Label3" Label="電話" Text="0551-1234567" runat="server" /> 8 <f:Label ID="Label16" runat="server" Label="申請人" Text="admin"> 9 </f:Label> 10 </Items> 11 </f:FormRow> 12 <f:FormRow> 13 <Items> 14 <f:Label ID="Label4" Label="編號" Text="200804170006" runat="server" /> 15 <f:TextBox ID="TextBox2" Required="true" ShowRedStar="true" Label="電子郵箱" RegexPattern="EMAIL" 16 RegexMessage="請輸入有效的郵箱地址!" runat="server"> 17 </f:TextBox> 18 </Items> 19 </f:FormRow> 20 <f:FormRow> 21 <Items> 22 <f:DropDownList ID="DropDownList3" Label="審批人" runat="server" ForceSelection="false" Required="true" ShowRedStar="True"> 23 <f:ListItem Text="老大甲" Value="0"></f:ListItem> 24 <f:ListItem Text="老大乙" Value="1"></f:ListItem> 25 <f:ListItem Text="老大丙" Value="2"></f:ListItem> 26 </f:DropDownList> 27 <f:NumberBox ID="NumberBox1" Label="申請數量" MaxValue="1000" Required="true" runat="server" 28 ShowRedStar="True" /> 29 </Items> 30 </f:FormRow> 31 <f:FormRow> 32 <Items> 33 <f:DatePicker runat="server" Required="true" Label="日期" EmptyText="請選擇日期" 34 ID="DatePicker1" SelectedDate="2014-07-10" ShowRedStar="True"> 35 </f:DatePicker> 36 <f:TimePicker ID="TimePicker1" ShowRedStar="True" Label="時間" Increment="30" 37 Required="true" Text="08:30" EmptyText="請選擇時間" runat="server"> 38 </f:TimePicker> 39 </Items> 40 </f:FormRow> 41 42 <f:FormRow> 43 <Items> 44 <f:FileUpload runat="server" ID="filePhoto" EmptyText="請選擇一張照片" Label="個人頭像" Required="true" 45 ShowRedStar="true"> 46 </f:FileUpload> 47 </Items> 48 </f:FormRow> 49 <f:FormRow> 50 <Items> 51 <f:TextArea ID="TextArea1" runat="server" Label="描述" ShowRedStar="True" Required="True"> 52 </f:TextArea> 53 </Items> 54 </f:FormRow> 55 <f:FormRow> 56 <Items> 57 <f:CheckBoxList ID="CheckBoxList1" Label="核取方塊列表" ColumnNumber="3" runat="server"> 58 <f:CheckItem Text="可選項 1" Value="value1" /> 59 <f:CheckItem Text="可選項 2" Value="value2" Selected="true" /> 60 <f:CheckItem Text="可選項 3" Value="value3" Selected="true" /> 61 <f:CheckItem Text="可選項 4" Value="value4" Selected="true" /> 62 <f:CheckItem Text="可選項 5" Value="value5" Selected="true" /> 63 </f:CheckBoxList> 64 </Items> 65 </f:FormRow> 66 <f:FormRow> 67 <Items> 68 <f:RadioButtonList ID="RadioButtonList2" Label="單選框列表" ColumnNumber="3" runat="server"> 69 <f:RadioItem Text="可選項 1" Value="value1" /> 70 <f:RadioItem Text="可選項 2" Value="value2" /> 71 <f:RadioItem Text="可選項 3" Value="value3" Selected="true" /> 72 <f:RadioItem Text="可選項 4" Value="value4" /> 73 <f:RadioItem Text="可選項 5" Value="value5" /> 74 </f:RadioButtonList> 75 </Items> 76 </f:FormRow> 77 </Rows> 78 </f:Form> 79 <br /> 80 <f:Button ID="btnDisableAll" Text="全部禁用" CssClass="marginr" runat="server" OnClick="btnDisableAll_Click"> 81 </f:Button> 82 <f:Button ID="btnEnableAll" Text="全部啟用" CssClass="marginr" runat="server" OnClick="btnEnableAll_Click"> 83 </f:Button> 84 <f:Button ID="btnReadOnlyAll" Text="全部只讀" CssClass="marginr" runat="server" OnClick="btnReadOnlyAll_Click"> 85 </f:Button> 86 <f:Button ID="btnCancelReadOnlyAll" Text="取消只讀" CssClass="marginr" runat="server" OnClick="btnCancelReadOnlyAll_Click"> 87 </f:Button> 88 <br /> 89 <br /> 90 <f:Button ID="btnMarkInvalid" Text="設定無效標識" CssClass="marginr" runat="server" OnClick="btnMarkInvalid_Click"> 91 </f:Button> 92 <f:Button ID="btnClearInvalid" Text="取消無效標識" CssClass="marginr" runat="server" OnClick="btnClearInvalid_Click"> 93 </f:Button>
後臺程式碼
因為幾個按鈕的邏輯類似,這裡我們定義一個代理(delegate),把相同的邏輯放在一個函式中完成,如下所示:
1 private delegate void ProcessFormField(Field field); 2 3 private void ResolveFormField(ProcessFormField process) 4 { 5 foreach (FormRow row in Form1.Rows) 6 { 7 foreach (Field field in row.Items) 8 { 9 if (field != null) 10 { 11 process(field); 12 } 13 } 14 } 15 }
幾個按鈕的只需要呼叫剛剛定義的ResolveFormField函式,並傳入自己的代理實現即可:
1 protected void btnDisableAll_Click(object sender, EventArgs e) 2 { 3 ResolveFormField(delegate(Field field) 4 { 5 field.Enabled = false; 6 }); 7 } 8 9 protected void btnEnableAll_Click(object sender, EventArgs e) 10 { 11 ResolveFormField(delegate(Field field) 12 { 13 field.Enabled = true; 14 }); 15 } 16 17 protected void btnReadOnlyAll_Click(object sender, EventArgs e) 18 { 19 ResolveFormField(delegate(Field field) 20 { 21 if (!(field is Label)) 22 { 23 field.Readonly = true; 24 } 25 }); 26 } 27 28 protected void btnCancelReadOnlyAll_Click(object sender, EventArgs e) 29 { 30 ResolveFormField(delegate(Field field) 31 { 32 if (!(field is Label)) 33 { 34 field.Readonly = false; 35 } 36 }); 37 } 38 39 protected void btnMarkInvalid_Click(object sender, EventArgs e) 40 { 41 ResolveFormField(delegate(Field field) 42 { 43 if (!(field is Label)) 44 { 45 field.MarkInvalid("這個欄位出錯了!"); 46 } 47 }); 48 } 49 50 protected void btnClearInvalid_Click(object sender, EventArgs e) 51 { 52 ResolveFormField(delegate(Field field) 53 { 54 if (!(field is Label)) 55 { 56 field.ClearInvalid(); 57 } 58 }); 59 }
本章小結
本篇文章介紹瞭如何對錶單內全部欄位進行批次操作,要注意禁用和只讀的區別,雖然兩種情況下表單欄位都不響應使用者動作,但還是有一些細微的差別,首先是顏色的變化不同,其次只讀時會隱藏TriggerBox右側的觸發按鈕。
後臺的程式碼實現用到了C#代理(delegate),從JavaScript的角度看其實就是個回撥函式,只不過C#的強型別限制,必須把這個回撥函式抽象成一個型別而已。
專業版截圖
FineUI(專業版)是由三生石上全新打造的基於 jQuery 的專業 ASP.NET 控制元件庫,計劃在七月下旬正式釋出。
選擇FineUI(專業版)的四大理由:
1. 簡單:專業版和開源版相容(v4.x),您現在就可以使用開源版進行開發,等正式版釋出時只需替換 DLL 即可。
2. 極速:專業版基於 jQuery 庫重寫,使得 JS 和 CSS 體積大幅減少,頁面載入速度將是開源版的 2 倍以上。
3. 多彩:專業版內建 24 種 jQueryUI 皮膚,使用者還可以使用 jQueryUI ThemeRoller 建立專屬自己的皮膚。
4. 便宜:專業版不限開發者數量和永久免費升級,使得典型授權案例的費用減少為開源版的 1/3 左右。
宣告:
- FineUI(專業版)授權協議是商業授權,需購買使用。
- FineUI(開源版)授權協議是Apache License v2.0,免費下載使用,並且會繼續維護和開發,個人使用者推薦使用開源版。
原始碼與線上示例
本系列所有文章的原始碼均可自行下載:http://fineui.codeplex.com/
線上示例(暫時不可用):http://fineui.com/demo/#/demo/form/form_disabled.aspx
這個示例會新增到下個版本的FineUI(開源版)中,因此線上示例還不可見,需要的同學請自行下載全部原始碼,自己執行。
如果本文對你有所啟發或者幫助,請猛擊“好文要頂”,支援原創,支援三石!