GridView
是由一組字段(
Field
)組成的,它們都指定的了來自
DataSource
中的什么屬性需要用到自己的輸出呈現(xiàn)中。最簡單的字段類型是
BoundField
,它僅將數(shù)據(jù)簡單的顯示為文本。其他的字段類型使用交互
HTML
元素(
alternate HTML elements
)來顯示數(shù)據(jù)。比如說,
CheckBoxField
將被呈現(xiàn)為一個
CheckBox
,其選中狀態(tài)由某特定數(shù)據(jù)字段的值來決定;
ImageField
則將某特定數(shù)據(jù)字段呈現(xiàn)為一個圖片,當然,這個數(shù)據(jù)字段中應該放的是圖片類型的數(shù)據(jù)。超級鏈接和按鈕的狀態(tài)取決于使用
HyperLinkField
或
ButtonField
字段類型的數(shù)據(jù)字段的值。
雖然
CheckBoxField
、
ImageField
、
HyperLinkField
和
ButtonField
考慮到了數(shù)據(jù)的交互視圖,但它們仍然有一些相關的格式化的限制。
CheckBoxField
只可以顯示為一個單個的
CheckBox
,而一個
ImageField
則只可以顯示為一張圖片。如果某個字段要顯示一些文本、復選框、圖片還有一些其他基于不同數(shù)據(jù)的東西的時候,我們要做什么?或者說,如果我們需要使用除了
CheckBox
、
Image
、
HyperLink
以及
Button
之外的
Web
控件來顯示數(shù)據(jù)時,我們該怎么辦?此外,
BoundField
只能顯示一個單獨的數(shù)據(jù)字段。如果我們想要在一個
GridView
列中顯示兩個或者更多的數(shù)據(jù)字段的值的時候該怎么辦呢?
為了適應這樣的一個復雜的情況,
GridView
提供了使用模板來進行呈現(xiàn)的
TemplateField
。模板可以包括靜態(tài)的
HTML
、
Web
控件以及數(shù)據(jù)綁定的代碼。此外,
TemplateField
還擁有各種可以用于不同情況的頁面呈現(xiàn)的模板。比如說,
ItemTemplate
是默認的用于呈現(xiàn)每行中的單元格的,而
EditItemTemplate
則用于編輯數(shù)據(jù)時的自定義界面。
在本節(jié)教程中,我們將解釋如何使用
TemplateField
來更加高級的自定義
GridView
控件。在
上一節(jié)教程
中,我們看到了如何使用
DataBound
和
RowDataBound
事件處理方法
來
自定義基于數(shù)據(jù)的格式化。另一個辦法就是在模板中調用一個格式化方法。在本節(jié)中,我們就會看到這種技術。
在本節(jié)中,我們將使用一些
TemplateField
來自定義雇員信息的呈現(xiàn)。特別的,我們將列出所有的雇員,但我們將會把雇員的姓和名字放在一列中,把他們的雇傭日期放在一個
Calendar
控件中,還將用一個狀態(tài)列來表明他們來到公司有多久了。
圖一:使用三個
TemplateField
來自定義信息的顯示方式
第一步:將數(shù)據(jù)綁定到GridView
當你需要使用一些
TemplateField
來自定義顯示時,我發(fā)現(xiàn)最簡單的就是先創(chuàng)建一個僅包含
BoundField
的
GridView
控件,然后添加一些
TemplateField
,如果需要的話,也可以將某些
BoundField
直接轉換成
TemplateField
。好了,讓我們開始本節(jié)教程吧。首先,通過設計器往頁面上添加一個
GridView
控件,并將一個返回雇員信息的
ObjectDataSource
綁定到它上面。這些步驟將創(chuàng)建一個帶有一些
BoundField
的
GridView
,這些
BoundField
對應雇員信息中不同的字段。
打開
GridViewTemplateField.aspx
,并從工具箱中拖一個
GridView
到設計器上。從
GridView
的智能標簽(
smart tag
)上選擇并添加一個新的調用
EmployeesBLL
類的
GetEmployees()
方法的
ObjectDataSource
控件。
圖二:添加一個新的調用
GetEmployees()
方法的
ObjectDataSource
控件
用這種方式綁定
GridView
將會自動的為雇員信息的每一個屬性添加一個
BoundField
:
EmployeeID
、
LastName
、
FirstName
、
Title
、
HireDate
、
ReportsTo
以及
Country
。在這個報表中,我們不希望看到
EmployeeID
、
ReportsTo
以及
Country
屬性。要刪除這些
BoundField
的話,你可以:
·????????
使用字段對話框
-
在
GridView
的智能標簽的彈出菜單中點擊“編輯列”(
Edit Columns
)。然后,在左下角的列表中選中你想要刪除的
BoundField
并點擊那個帶紅叉的按鈕,就可以刪除這個
BoundField
了。
·???????? 手工編輯 GridView 的聲明語句 - 在源視圖( Source view )中,找到你想要刪除的 BoundField ,就是那些 <asp:BoundField> 元素,刪了就行了 。
在你刪了
EmployeeID
、
ReportsTo
和
Country
等
BoundField
之后,你的
GridView
的標記語言代碼應該像這個樣子:

?2

?3

?4

?5

?6

?7

?8

?9

10

讓我們花點時間在瀏覽器中來看看我們的成果。這時,你將看到一個表格,表格中每一個記錄都是一個雇員的信息,一共有四列:一個是雇員的姓,一個是名字,一個是頭銜,還有一個是他們的受雇日期。
圖三:每一個雇員信息都顯示了
LastName
、
FirstName
、
Title
和
HireDate
第二步:將姓和名顯示在一列中
現(xiàn)在,每一個雇員的姓和名都是分開在兩列中顯示的。把它們放到一個列中顯示出來也許是一個不錯的主意。要做到這一點,我們需要用到
TemplateField
。我們可以添加一個新的
TemplateField
,給它加上一些必須的標記語言和數(shù)據(jù)綁定代碼,然后刪除原來的
FirstName
和
LastName
這兩個
BoundField
;當然,我們也可以將
FirstName
這個
BoundField
直接轉換成一個
TemplateField
,編輯它以加上
LastName
的值,然后再刪除
LastName
這個
BoundField
。
兩種辦法都行,不過我個人還是比較喜歡直接轉換的那種,因為這種方式可以自動的添加一個含有
Web
控件和相應的數(shù)據(jù)綁定代碼的
ItemTemplate
和
EditItemTemplate
,它們可以用來模仿一個
BoundField
的呈現(xiàn)和功能。這樣做的好處自然是不言而喻的,因為轉換的過程已經(jīng)幫我們做了很多事情,那我們當然就可以節(jié)約不少的時間了。
要將一個
BoundField
轉換成
TemplateField
,我們可以在
GridView
的智能標簽的彈出菜單中點擊“編輯列”(
Edit Columns
)。在彈出對話框的左下角的列表中選擇需要轉換的
BoundField
,然后點擊右下角的“將此列轉換成模板列”(
Convert this field into a TemplateField
)即可。
圖四:在字段對話框中,將一個綁定列轉換成一個模板列
讓我們繼續(xù)將
FirstName
這個
BoundField
轉換成
TemplateField
。在這個更改之后,設計器中并沒有什么明顯的不同。這是因為將
BoundField
轉換成
TemplateField
時,其實是創(chuàng)建了一個維持之前的
BoundField
的外觀和感覺的
TemplateField
。盡管在設計器中沒有視覺上的變化,但是這個轉換的過程已經(jīng)將
BoundField
的聲明代碼——
<asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression="FirstName" />
——改成了如下所示的
TemplateField
的聲明代碼:

2

3

4

5

6

7

8

9

就像你看到的那樣,
TemplateField
由兩個模板組成——一個
ItemTemplate
,它有一個
Label
控件,其
Text
屬性被設置為
FirstName
數(shù)據(jù)字段的值;還有一個
EditItemTemplate
,它有一個
TextBix
控件,其
Text
屬性也被設置為
FirstName
數(shù)據(jù)字段的值。數(shù)據(jù)綁定語法——
<%# Bind("fieldName") %>
——說明數(shù)據(jù)字段
fieldName
被綁定到了這個特定的
Web
控件的屬性上。
要將
LastName
添加到
TemplateField
中,我們需要為
ItemTemplate
添加一個
Label
控件并將其
Text
屬性綁定到
LastName
上。通過設計器或是手工編寫代碼都可以做到這一點。要手工寫代碼的話,只需簡單的將相應的聲明代碼添加到
ItemTemplate
中即可,如下所示:

?2

?3

?4

?5

?6

?7

?8

?9

10

要通過設計器來添加的話,還是在
GridView
的智能標簽的彈出菜單中點擊“編輯列”(
Edit Templates
)。這樣會顯示
GridView
的模板編輯界面。在這個界面中,智能標簽是
GridView
中模板的列表。因為這個時候我們只有一個
TemplateField
,所以下拉列表中只有
FirstName
的各種模板和
EmptyDataTemplate
以及
PagerTemplate
。如果指定了
EmptyDataTemplate
模板的話,它將用于綁定到
GridView
的數(shù)據(jù)源中沒有任何記錄時的輸出呈現(xiàn);如果指定了
PagerTemplate
,它將用于呈現(xiàn)
GridView
的分頁界面。
圖五:
GridView
的模板列可以通過設計器來編輯
要在
FirstName
模板列中同時顯示
LastName
,從工具箱中拖一個
Label
到
FirstName
模板列的
ItemTemplate
中即可,當然,這要在
GridView
的模板編輯界面中才行的,如下圖所示:
圖六:向
FirstName
模板列的
ItemTemplate
中添加一個
Label
現(xiàn)在,添加到
TemplateField
的
Label
控件的
Text
屬性還是“
Label
”。我們需要修改這個以使這個屬性綁定到數(shù)據(jù)源中的
LastName
字段上。我們可以通過在
Label
控件的智能標記上點擊一下,然后在彈出菜單中選擇“編輯數(shù)據(jù)綁定”(
Edit DataBindings
)選項,如下圖所示:
圖七:從
Label
的智能標簽上選擇
Edit DataBindings
選項
在彈出的數(shù)據(jù)綁定對話框中,你可以在左邊的列表中選擇需要綁定的屬性,然后在右邊的下來框中選擇一個數(shù)據(jù)字段。好了,我們現(xiàn)在在左邊選擇
Text
屬性,然后在右邊選擇
LastName
字段,點擊
OK
。
圖八:將
Text
屬性綁定到
LastName
字段上
注意:
數(shù)據(jù)綁定對話框允許你聲明一個雙向的數(shù)據(jù)綁定。如果你保持“雙向數(shù)據(jù)綁定”
(
Two-way databinding
)這個復選框為未選中的話,數(shù)據(jù)綁定的代碼將會是
<%# Eval("LastName")%>
而不是
<%# Bind("LastName")%>
。不過,對于本節(jié)教程來說,兩個種做法的效果都是
OK
的。雙向數(shù)據(jù)綁定在插入和編輯數(shù)據(jù)的時候將會比較重要。但是如果僅僅是簡單的顯示數(shù)據(jù)的話,兩種做法都是一樣的。我們將在今后的章節(jié)中詳細的討論一下雙向數(shù)據(jù)綁定。
讓我們再花一些時間到瀏覽器中看看這個頁面。就像你看到的那樣,
GridView
仍然包含
4
列,不過,
FirstName
列里面顯示了姓和名兩個數(shù)據(jù)。
圖九:姓和名顯示在同一列里面了
要完成這一步,我們先刪除
LastName
這個綁定列,并將
FirstName
這個模板列的列頭文本(
HeaderText
)改成“
Name
”。在這之后,
GridView
的聲明代碼將會像下面這樣:

?2

?3

?4

?5

?6

?7

?8

?9

10

11

12

13

14

15

16

17


圖十:每一個雇員的姓和名都顯示在同一列里面了
第三步:使用Calendar控件顯示HiredDate字段
在
GridView
中將數(shù)據(jù)顯示為文本的話,只需要簡單的使用
BoundField
就可以了。然而,在某些特定的場合,數(shù)據(jù)最好是展示為一個特殊的
Web
控件而不是一個簡單的文本。這樣的自定義的數(shù)據(jù)顯示就可以用
TemplateField
來做。比如說,比起將雇員的雇傭日期顯示成文本來說,我們覺得將其高亮的顯示在一個
Calendar
(使用
Calendar控件
)中會更爽一些。
要做到這一點,先將
HiredDate
這個綁定列轉換成一個模板列。像之前做的那樣轉換就是了,大家應該還沒有忘記吧?在
GridView
的智能標簽那里下手就可以了。
圖十一:將
HiredDate
綁定列轉換成一個模板列
就像我們在第二步中看到的那樣,這個操作會將綁定列替換成一個含有
ItemTemplate
和
EditItemTemplate
的模板列,其中的
ItemTemplate
和
EditItemTemplate
分別帶有一個
Label
和一個
TextBox
,而這個
Label
和
TextBox
的
Text
屬性都使用了數(shù)據(jù)綁定語句
<%# Bind("HiredDate")%>
來將
HireDate
綁定到自己身上。
要用
Calendar
控件來替換這個文本的話,我們可以編輯模板:刪除
Label
控件,并添加上一個
Calendar
控件。在設計器中,從
GridView
的智能標簽的彈出菜單中選擇“編輯模板”(
Edit Templates
),并在下拉列表中選擇
HireDate
模板列的
ItemTemplate
。然后,刪除
Label
控件并從工具箱中拖一個
Calendar
控件到模板編輯界面中。
圖十二:給
HireDate
模板列的
ItemTemplate
添加一個
Calendar
控件
這個時候,
GridView
中每一行的
HireDate
模板列都會包含一個
Calendar
控件。不過,雇員的實際雇傭日期還沒有設置到
Calendar
控件上,這就讓
Calendar
控件默認的顯示為當前的日期。我們可以通過將雇員的
HireDate
賦值給
Calendar
控件的
SelectedDate
和
VisibleDate
屬性來修正這個問題。
從
Calendar
控件的智能標簽中選擇“編輯數(shù)據(jù)綁定”。然后,把
SelectedDate
和
VisibleDate
這兩個屬性都綁定到
HireDate
字段上。
圖十三:將
SelectedDate
和
VisibleDate
都綁定到
HireDate
字段上
注意:
Calendar
控件的選定日期不一定要可見。舉個例子來說,某個
Calendar
控件的選定日期為
1999
年
4
月
1
日,但卻顯示的是現(xiàn)在的年月。選定日期和可見日期是由
Calendar
控件的
SelectedDate
和
VisibleDate
屬性來指定的。因為我們不僅希望選中雇員的
HireDate
,還希望它是可見的,那么我們就需要將這兩個屬性都綁定到
HireDate
字段上。
現(xiàn)在,我們再到瀏覽器中看看這個頁面,
Calendar
現(xiàn)在顯示的是雇員的雇員受雇日期的月份并選中了一個指定的日期。
圖十四:雇員的受雇日期顯示到了
Calendar
控件上
注意:
和我們一直所見到的那些例子相反,在本節(jié)教程中我們并沒有將
GridView
的
EnableViewState
屬性設置為
false
。這樣做的原因是,在
Calendar
控件上的點擊將會產(chǎn)生一個回發(fā)(
PostBack
),并將
Calendar
的選定日期設置為剛才所點擊的那個日期。如果禁用了
GridView
的
ViewState
,那么每一次回發(fā)都將導致
GridView
使用原來的數(shù)據(jù)重新綁定,這樣
Calendar
的選定日期就會變成原來的雇員受雇日期。
在本教程中,這是一個沒有意義的議題,因為用戶本來就不應該可以修改雇員的受雇日期??赡苤苯优渲?/span>
Calendar
控件為不可選是最好的辦法。不過不管怎么說,在本教程中可以看到,某些情況下還是將控件的
ViewState
啟用才能提供某些特定的功能的。
第四步:顯示雇員在公司工作了多少天
到現(xiàn)在,我們已經(jīng)看到了
TemplateField
的兩個應用:
·???????? 將兩個數(shù)據(jù)合并到一個列中
·????????
用一個
Web
控件來展示數(shù)據(jù),而不是用一個簡單的文本
第三種
TemplateField
的用法是,顯示
GridView
中數(shù)據(jù)的元數(shù)據(jù)。比如說,除了顯示雇員的受雇日期,我們可能還希望用一列來顯示這個雇員在公司干了多久。
另外還有一種用法,它將在某些情況下需要用到,比如說在頁面上某個數(shù)據(jù)的顯示格式需要用一種不同于其在數(shù)據(jù)庫中的存儲格式的時候。想象一下,雇員表中有一個性別字段,其中存儲了
M
或是
F
這樣的字符用于表示此雇員是男的還是女的。當我們需要將這個信息顯示在頁面上的時候,我們可能希望能夠將其顯示為“男”或“女”而不是“
M
”或“
F
”。
這兩種用法都可以采用在
ASP.NET
頁面的后置代碼類(或者是在一個獨立的類庫中,將其實現(xiàn)為一個靜態(tài)方法)創(chuàng)建一個供模板調用的格式化方法(
formatting method
)來做到。這樣的格式化方法將在模板中調用,語法跟前面的數(shù)據(jù)綁定語法是一樣的。格式化方法可以接受若干個參數(shù),但是必須返回一個字符串。這個返回的字符串是一個用于插入到模板中的
HTML
。
讓我們增加一點內容來說明這個概念。主要是增加一列以顯示雇員在公司干活的天數(shù)。這個格式化方法接受一個
Northwind.EmployeesRow
對象,然后返回以字符串的形式返回這個雇員在公司干活的天數(shù)。這個方法可以添加到
ASP.NET
頁面的后置代碼類中,不過一定要記得將其標記為
protected
或
public
,不然模板就訪問不到它了。

?2



?3

?4

?5

?6

?7



?8

?9

10

11

12

13

由于
HiredDate
可能會含有空值,所以我們必須在進行計算之前首先保證其值不為空。如果
HiredDate
值為空的話,直接返回一個“
Unknown
”就是了;如果不為空的話呢,就計算當前時間跟
HiredDate
的值之間所隔的天數(shù),并把它作為一個字符串返回即可。
要使用這個方法,我們需要在
GridView
的
TemplateField
中使用數(shù)據(jù)綁定語法來調用它。同樣,我們還是先給
GridView
添加一個新的模板列。
?
圖十五:給
GridView
添加一個新的模板列
將這個新的模板列的頁眉文本(
HeaderText
)設置成“
Days on the Job
”,并將其
ItemStyle
的水平對齊(
HorizontalAlign
)設置為居中(
Center
)。要調用
DisplayDaysOnJob
方法,我們需要給這個模板列添加一個
ItemTemplate
并加上如下的數(shù)據(jù)綁定代碼:



Container.DataItem
返回數(shù)據(jù)源對象中的一個相應的
DataRowView
對象給
GridView
。它的
Row
屬性返回一個強類型化的
Nothwind.EmployeesRow
,然后再將其傳遞給
DisplayDaysOnJob
方法。這個數(shù)據(jù)綁定語法可以直接出現(xiàn)再
ItemTemplate
(就像下面的代碼中那樣)中或是賦值給
Label
控件的
Text
屬性。
注意:
除了傳遞一個
EmployeesRow
的實例,其實我們也可以僅僅傳遞
HireDate
的值,使用
<%# DisplayDaysOnJob(Eval("HireDate")) %>
就可以了。不過呢,
Eval
方法將返回一個
object
類型,所以我們就必須要修改
DisplayDaysOnJob
方法的簽名以使其可以接受一個
object
類型的參數(shù)。我們不能將
Eval("HireDate")
調用的結果隱式的轉換成一個
DateTime
類型,因為
Employees
表的
HireDate
字段是允許為空的。因此,我們需要使
DisplayDaysOnJob
方法可以接受一個
object
類型的參數(shù),并判斷這個參數(shù)是不是空值(我們可以使用
Convert.IsDBNull(
objectToCheck
)
來完成這個驗證工作),然后再進行后面的操作。
就是因為這個,所以我還是選擇了傳遞整個
EmployeesRow
實例。在下一節(jié)教程中,我們會看到一個更加合適使用
Eval("columnName")
來傳遞參數(shù)給格式化方法的例子。
在給我們的
GridView
添加了模板列并在
ItemTemplate
中添加了調用
DisplayDaysOnJob
方法的代碼后,聲明代碼應該是這個樣子:

?2

?3

?4

?5

?6

?7

?8

?9

10

11

12

13

14

15

16

17

18

19

20



21

22

23

24

25



26

27

28

29

30

31

完成了整節(jié)教程之后,頁面在瀏覽器中的樣子應該是圖十六的這個樣子。
圖十六:“雇員在公司干了多久“也顯示出來了
總結 ?
?
在
GridView
控件中,相對于其他的列控件來說,模板列可以處理更加復雜的數(shù)據(jù)呈現(xiàn)。模板列主要用于這樣一些情況:
·???????? 一個 GridView 列中需要顯示多個數(shù)據(jù)列
·???????? 使用一個 Web 控件來展示數(shù)據(jù)比一段簡單的文本更好
·???????? 頁面的輸出取決于綁定到 GridView 的數(shù)據(jù),比如說元數(shù)據(jù)或者說是數(shù)據(jù)的重新格式化
除了自定義數(shù)據(jù)的顯示,模板列也用于編輯和插入數(shù)據(jù)時的用戶界面的自定義,這個我們在后面的章節(jié)中將會講到。
接下來的兩節(jié)中,我們會繼續(xù)討論模板,我們會先看看在
DetailsView
中使用模板列的情況。跟著我們再去看看
FormView
,這玩意兒就是用模板來實現(xiàn)一個更加復雜的呈現(xiàn),當然,用的是一大堆的字段。