導言
在上兩節教程中,我們看到了如何使用TemplateField來自定義GridView和DetailsView的輸入。TemplateField使我們可以高度自主的定義某個特定的列,但不管是GridView還是DetailsView,都會有點太規則了,簡單的說就是它們都有著四四方方的格子一樣的外觀。很多情況下這樣的格子一樣的外觀是很不錯的,不過有的時候我們卻需要使用一個不規則的顯示外觀。當需要顯示一個單獨的記錄時,使用FormView控件就可以實現這種比較隨意的外觀呈現。
跟DetailsView不同,FormView並不是由那些雜七雜八的列所組成的。你不能給一個FormView添加BoundField或是TemplateField,不過FormView是使用模板來呈現的。我們可以這樣來理解FormView,把它當作只含有一個TemplateField的DetailsView控件。FormView支持以下這些模板:
· ItemTemplate – 用於在FormView種呈現一個特殊的記錄
· HeaderTemplate – 用於指定一個可選的頁眉行
· FooterTemplate –用於指定一個可選的頁腳行
· EmptyDataTemplate – 當FormView的DataSource缺少記錄的時候,EmptyDataTemplate將會代替
ItemTemplate來生成控件的標記語言
· PagerTemplate – 如果FormView啟用了分頁的話,這個模板可以用於自定義分頁的界面
· EditItemTemplate / InsertItemTemplate – 如果FormView支持編輯或插入功能,那麼這兩種模板可以用於自定義相關的界面
在本節教程中,我們將解釋如何使用FormView控件來為產品呈現一個不規則的外觀。FormView的ItemTemplate將會使用一個頁眉元素和<table>的結合體來顯示名稱、分類、供應商等等的值,而不是使用各種各樣的列(如圖一所示)。
圖一:FormView打破了DetailsView的那種格子一樣外觀
第一步:將數據綁定到FormView
打開FormView.aspx頁面,並從工具箱中拖一個FormView到設計器中。FormView剛剛添加到頁面上時,它就是一個灰色的方塊,這就告訴我們它需要一個ItemTemplate。
圖二:FormView在添加一個ItemTemplate之前是不會在設計器中呈現出來的
可以手工編寫代碼(在源視圖中)來添加ItemTemplate,也可以通過在設計器中將FormView綁定到一個數據源控件上來實現自動添加。這個自動生成的ItemTemplate包含了用於顯示各字段的名稱的HTML代碼,還有用於顯示各字段的值的Label控件,當然了,這些Label控件的Text屬性都已經綁定到了各相應的字段上。這個操作也同時生成了InsertItemTemplate和EditItemTemplate,它們為數據源控件的每一個字段都呈現了一個輸入控件。
如果你想要自動生成模板,首先應該使用ProductsBLL類的GetProducts()方法來給FormView添加一個ObjectDataSource控件,通過FormView的智能標簽你就可以做到上面的這個操作。這樣就可以創建一個帶有ItemTemplate、InsertItemTemplate和EditItemTemplate的FormView了。在源視圖中,刪除InsertItemTemplate和EditItemTemplate,因為我們現在對創建一個可編輯和可插入的FormView並不感興趣。然後,清空ItemTemplate中的標記語言代碼,這樣我才可以工作於一個干淨的環境上。
如果你喜歡手工建立ItemTemplate,你可以從工具箱中拖一個ObjectDataSource到設計器中並配置它,這裡可不要在設計器中為FormView添加數據源。我們應該到源視圖中手工的將ForView的DataSourceID屬性設置為ObjectDataSource的ID,然後再手工添加ItemTemplate。不管你決定使用哪種方式,反正最後你的FormView的聲明標記代碼應該像下面這個樣子:
<asp:FormView ID="FormView1" runat="server" DataSourceID="ObjectDataSource1"> <ItemTemplate> </ItemTemplate> </asp:FormView>
花點兒時間到FormView的智能標簽中勾上“啟用分頁(Enable Paging)”復選框,這樣可以在FormView的聲明標記代碼中加上AllowPaging="True"這麼一個屬性(attribute)。另外,把EnableViewState屬性設置為false。
第二步:定義ItemTemplate的標記代碼(MarkUp)
在將FormView綁定到ObjectDataSource控件並且將其配置為支持分頁之後,我們就准備指定ItemTemplate的內容了。在本教程中,讓我們將產品名稱顯示在一個<h3>中。跟著讓我們使用<table>將余下的產品屬性顯示在一個四列的表中,其中第一列和第三列用於顯示產品屬性的名稱,第二列和第四列用於顯示產品屬性的值。
在設計器中通過FormView的模板編輯界面或是在源視圖中手工輸入代碼都可以添加上面所說的這些標記代碼。使用模板的時候,我發現直接在源視圖中編代碼會來得比較快,不過你可以使用任何一種讓你覺得夠爽的方式。下面的聲明標記代碼展示了FormView在完成了ItemTemplate的結構之後所應該有的樣子:
<asp:FormView ID="FormView1" runat="server" DataSourceID="ObjectDataSource1" AllowPaging="True" EnableViewState="False"> <ItemTemplate> <hr /> <h3><%# Eval("ProductName") %></h3> <table border="0"> <tr> <td class="ProductPropertyLabel">Category:</td> <td class="ProductPropertyValue"> <%# Eval("CategoryName") %></td> <td class="ProductPropertyLabel">Supplier:</td> <td class="ProductPropertyValue"> <%# Eval("SupplierName")%></td> </tr> <tr> <td class="ProductPropertyLabel">Price:</td> <td class="ProductPropertyValue"><%# Eval("UnitPrice", "{0:C}") %></td> <td class="ProductPropertyLabel">Units In Stock:</td> <td class="ProductPropertyValue"> <%# Eval("UnitsInStock")%></td> </tr> <tr> <td class="ProductPropertyLabel">Units On Order:</td> <td class="ProductPropertyValue"> <%# Eval("UnitsOnOrder") %></td> <td class="ProductPropertyLabel">Reorder Level:</td> <td class="ProductPropertyValue"> <%# Eval("ReorderLevel")%></td> </tr> <tr> <td class="ProductPropertyLabel">Qty/Unit</td> <td class="ProductPropertyValue"> <%# Eval("QuantityPerUnit") %></td> <td class="ProductPropertyLabel">Discontinued:</td> <td class="ProductPropertyValue"> <asp:CheckBox runat="server" Enabled="false" Checked='<%# Eval("Discontinued") %>' /> </td> </tr> </table> <hr /> </ItemTemplate> </asp:FormView>
注意這個數據綁定語法——以<%# Eval("ProductName") %>為例——可以直接插入到模板的輸出中。那是因為它沒有必要綁定到一個Label控件的Text屬性上。舉個例子,比如我們要將ProductName的值使用<h3><%# Eval("ProductName") %></h3>來顯示在一個<h3>元素中,那麼產品“Chai”將被輸出為<h3>Chai</h3>。
CSS類ProductPropertyLabel和ProductPropertyValue用於指定<table>中的產品屬性的名稱和值的樣式。這些CSS類定義在Styles.css中,它們使產品屬性的名稱粗體顯示並且右對齊,它們還給產品屬性的值加上一個右填充。
由於FormView沒有CheckBoxField,要將Discontinued的值顯示為一個CheckBox的話,我們就必須自己添加一個CheckBox控件。將這個CheckBox控件的Enabled屬性設置為false以使其只讀,並將其Checked屬性綁定到Discontinued字段上去。
完成了ItemTemplate之後,產品信息就以一種更加不規則的方式來顯示了。來比較一下上一節中的DetailsView的輸出(圖三)和本節所討論的FormView的輸出(圖四)。
圖三:生硬的DetailsView輸出
圖四:柔和的FormView輸出
總結
雖然GridView和DetailsView控件可以使用TemplateField來自定義它們的輸出,不過它們都呈現為一種格子一樣的四四方方的樣子。在那些需要使用一種不規則的外觀來顯示一個單獨的記錄的時候,FormView就是一個理想的選擇。跟DetailsView一樣,FormView從它的DataSource中顯示一個單獨的記錄。不過它也有跟DetailsView不同的地方,它僅由模板組成,而且它根本不支持字段(fields。譯者注:比如說CheckBoxField)。
就像我們在本節中看到的那樣,在顯示一個單獨的記錄的時候,FormView提供了一種更加復雜的的呈現方式。在今後的教程中我們將解釋一下DataList和Repeater控件,它們可以提供跟FormView一樣復雜的呈現,不過它們可以顯示多列(就像GridView那樣)。
編程愉快!
關於作者
Scott Mitchell,著有六本ASP/ASP.NET方面的書,是4GuysFromRolla.com的創始人,自1998年以來一直應用微軟Web技術。Scott是個獨立的技術咨詢顧問,培訓師,作家,最近完成了將由Sams出版社出版的新作,24小時內精通ASP.NET 2.0。他的聯系電郵為[email protected],也可以通過他的博客http://ScottOnWriting.NET與他聯系。