GridView是ASP.NET界面開發中的一個重要的控件,對GridView使用的熟練程度直接影響軟件開發的進度及功能的實現。(車延祿)
GridView的主要新特性:
1.與DataSource控件結合實現了顯示與數據操作的分離,大大減化了代碼的編寫量;
2.實現"雙向綁定",無需手動檢索數據。
2.在列的類型上新增了CheckBoxField和ImageField兩個類型列;
3.對排序和分頁可以實現異步操作;
4.對其視圖狀態進行優化,使其運行效率更高;
GridView與DataSource控件
要談GridView就必需要談DataSource,這兩個對象可稱得上是“最佳拍檔”。DataSource控件負責與數據源的交互,而GridView負責數據的顯示。它們之間通過“雙向綁定”聯繫起來,即DataSource控件將檢索出來的數據綁定到GridView中顯示,而GridView中修改和刪除的數據直接綁定到DataSource數據源去。這兩個過程由這兩個控件相互配合實現的,無需我們編寫代碼。如果我們只用GridView顯示數據,而不用DataSource控件的話,那你只好編寫代碼實現DataSource要作的工作了。做爲用過VS2003的用戶對這個工作並不陌生,但這種代碼實現不但工作量大,而且使用複雜,容量產生大量可讀性差的代碼,當然也是初學者的最大障礙。好在VS2005爲我們提供了DataSource控件,使我們不再如此痛苦地Coding了(當然,如果有的情況下DataSource控件還無法完全替代Coding)。
所以在使用GridView控件的時候我們最好配合DataSource控件使用,不要再去折磨自己了。 下面的案例不做特殊說明均以GridView+DataSource控件實現。
一、GridView外觀設置:
1、總體外觀設置
ShowFooter:(bool)是否顯示頁腳
ShowHeader:(bool)是否顯示頁眉
GridLines:(enum)None-不顯示格線;Horizontal-顯示水平格線;Virtical-顯示豎直格線;Both-顯示水平和豎直格線
EmptyDataText:(string)如果數據源中內容爲NULL時在GridView中顯示的值
AlternatingRowStyle:交替項的樣式
EditRowStyle:編輯項的樣式
EmptyDataRowStyle:空數據項的樣式
FooterStyle:頁腳樣式
HeaderStyle:頁眉樣式
PagerStyle:分頁樣式
RowStyle:行樣式
SelectedRowStyle:選中項樣式
注:1、使用GridView的時候我們一般可以使用“自動套用樣式”選中一個樣式,然後在此樣式的基礎上修改上面的屬性,從而製作出滿意外觀效果。
2、上面的樣式可以對GridView進行總體的外觀設置,如果對某一列進行設置的話那可要在GridView右上角“智能菜單中”點擊“編輯列”進行設置。
如:
直接套用樣式後的外觀
修改RowStyle-BackColor、RowStyle-Font、RowStyle-HorizontalAlign 等屬性後的效果
2、對綁定列進行外觀設置
對上面的圖我們可以看出外觀方面有幾個問題:
a.頁眉是英文的
b.所有的數據都是居中對齊
c.time列的數據中顯示了時分秒的數據
d.price列中應加上"RMB"的符號
e.最好對價格列的數據以紅色字體顯示
上面的這些問題我們可以通地單獨對列進行格式設置來實現
點擊GridView右上角“智能菜單中”點擊“編輯列”,打開"字段"窗口:
這個圖總體可以分作三大部分:可用字段,選中的字段,BoundField屬性
(1)“可用字段”:顯示了可供我們使用的列的類型
BoundField:綁定列,將數據庫中的數據以字符形式綁定顯示
CheckBoxField:複選框列,一般用來綁定數據庫中的Bit型數,以複選框的形式顯示在GridView中
HyperLinkField:超鏈接列,可以用數據源中的數據作超鏈接文本也可以把所有超鏈接文本設爲統一的文本
ImageField:圖片列,綁定數據源中的圖片路徑,並把圖片顯示出來
CommandField:命令列,常用的“選擇”,“刪除”,“編輯、更新、取消”
ButtonField:按鈕列,其它做用的按鈕
TemplateField:模板列,可以更靈活地自定義顯示格式
(2)“選定的字段”:從“可用字段”中添加進來的,用來在GridView中顯示的列。其下方有個複選框“自動生成字段”,如果選中了就會根據DataSource控件中檢索出來的數據自動生成列,如果你要自己設置列的格式,請將此複選框清空。(車延祿)
(3)“BoundField屬性”:設置“每個可用字段”的屬性
我們可以根據自己的需要從“可用字段”中選擇列添加到“選中的字段中”,然後設置BoundField屬性。
在此我們先主要看BoundField列,其它類型的列後面再講解。
BoundField中的重要屬性:
ControlStyle:當前列中控件的樣式
HeaderStyle:當前列中頁眉的樣式
FooterStyle:當前列中頁腳的樣式
ItemStyle:當前列中數據行的樣式
ReadOnly:當前列是否是隻讀列,編輯的時候不顯示文本框
SortExpression:排序表達式,這裏只填數據源的列名
Visible:當前列是否可見
HeaderText:頁眉文本
FooterText:頁腳文本
DataField:當前列的數據行要顯示哪個字段的數據,填寫字段名
DataFormatString:對顯示的數據進行格式化顯示
上面的屬性太多,大家可以一時記下來,其實也沒必要去記,只要見文知意就可以了。下面我們就用上面的內容來解決外觀方法的問題
第一步:清空“自動生成字段”複選框
第二步:從“可用字段”中選擇“BoundField”添加到“選定的字段”中
第三步:點擊“選定的字段”中的每個字段,在“BoundField屬性”中設置
HeaderText--頁眉文本。如:“汽車名稱”
DataField--要在此列顯示數據的列名
第四步:設置"name"列的ItemStyle中的HorizontalAlign屬性爲left,這樣只把name列的數據左對齊
第五步:設置"price"列的ItemStyle中的HorizontalAlign屬性爲right,這樣只把price列的數據右對齊
第六步:在time列的DataFormatString屬性中設置爲:"{0:d}"
第七步:在price列的DataFormatString屬性中設置爲:"<font color=red>RMB</font>{0}"
好了,大家可以看到上面的問題我們都已解決了,效果還可以吧。
3、對數據行進行外觀設計
對於列的設計我們可以通過可視化的界面進行設計,但是對於數據行的外觀設置就沒有那麼簡單了。由於我們不知道將來有多少行數據顯示,也不知道哪一條數據顯示在哪一行中,所以很難通過可視化的方式進行設置。但這並不代表我們沒有辦法根據綁定的數據不同設置不同行的外觀。
要解決這個問題我們先來研究一下GridView的綁定數據的過程:
當我們爲GridView設置了已配好數據源後,在運行的時候,會把數據源中的數據綁定顯示出來。但由於GridView隱藏了自身在數據綁定過程中的構建過程,所以使好多學JavaEE的同學感覺不如在<Table>標記中嵌入for循環清晰,更使有的同學感到“GridView自動生成的行讓人有點不太放心”。其實,這是個思維導向的問題,只要我們理解了在數據綁定時GridView界面的構建過程,就不難發現GridView數據綁定的思路並不複雜。關鍵的是大家不要羈絆於JavaEE生成表格的思路中,要以一種開放與求知的心態來研究GridView。
實際上在GridView在數據綁定的過程中是逐行實現的。是從GridView最上面的一行(頁眉或上分頁行)到最下面的一行(頁腳或下分頁行)逐行建造的。在建造每一行的過程中,又分爲兩步:創建行和綁定行兩個步驟。下面分開說:
創建行:就是根據數據源的結構創建出n個單元格,並根據GridView的樣式和BoundFField屬性的樣式設置好每個單元格的樣式(背景色,前景色,字體等)。如果該行中有控件或靜態文本(設計時已寫死的文本,如頁眉文本)那在創建的時候也會直接創建控件或靜態文本。就像開茶館一樣,把椅子、桌子、茶杯、開水都備好了,就等客人來了(客人還沒來呢,因爲這只是創建行,還沒有綁定行呢)。
綁定行:“創建行”執行完後,再進行“綁定行”。綁定行實際上就是把數據源中當前行的數據逐一填寫到已創建好的行的相應單元格里去。綁定行執行完畢時才真正把一行數據建造完畢。這裏就像把客人按排到相應的已準備好的坐位上喝茶。
在GridView綁定DataSource控件的時候實際上就是循環執行“創建行”和“綁定行”的過程。如果我們能深入到每一行的“建造”過程中去,我們就可以根據綁定出來的數據控制當前行的外觀樣式了。
非常幸運,GridView 爲我們提供了兩個事件:RowCreated和RowDataBound事件
RowCreated事件:是每一行“創建行”完成時被觸發的事件。
RowDataBound事件:是每一行“綁定行”完成時被觸發的事件。
因此在綁定GridView顯示數據過程也就是循環觸發RowCreated事件和RowDataBound事件的過程。
下面的代碼驗證了我上面的闡述:(車延祿)
protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
Response.Write(e.Row.RowType.ToString()+" Created=>");
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
Response.Write(e.Row.RowType.ToString()+" DataBound=>");
}
執行結果:
好了通過上面的講述,大家應當明白GridView的綁定過程了,也正有了上面的RowCreated和RowDataBound這兩個能被自動觸發的事件,我們就可以像孫猴子鑽入鐵扇公主的肚子裏那樣鑽入到GridView的創建過程中去,想怎麼拆騰就怎麼拆騰,完全由你了。
那下面我們就拆騰一下吧,對數據行實現下面的控制:
1.把“上市時間”列改爲"yyyy年MM月dd日"的中文格式顯示
2.把價格高於50萬元的高檔汽車用黃色前景和紅色字體顯示
3.計算當前頁面中所有汽車的平均價格,並顯示在頁腳中
解決思路:
在GridView控件的RowDataBound事件中,取得每一行中相應單元格中的數據,把數據處理,重新寫回單元格中。
代碼如下:
//成員變量,用來累計當前頁面中所有汽車的價格總和
private double _PriceSum;
protected void Page_Load(object sender, EventArgs e)
{
//顯示頁腳,以便在其中顯示平均價格
GridView1.ShowFooter = true;
}
//修改日期的顯示格式
private void ChangeDate(GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
if (e.Row.RowState == DataControlRowState.Normal || e.Row.RowState == DataControlRowState.Alternate)
{
//取出“上市時間”單元格中的日期文本
string dt = e.Row.Cells[3].Text;
if (dt != null && dt.Trim() != "")
{
//將日期轉換爲長日期字符串格式
e.Row.Cells[3].Text = Convert.ToDateTime(dt).ToLongDateString();
}
}
}
}
//把價格大於50萬的汽車用黃色背景紅色字體顯示
private void HighLightCar(GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
if (e.Row.RowState == DataControlRowState.Normal || e.Row.RowState == DataControlRowState.Alternate)
{
string strprice = e.Row.Cells[4].Text;//取出來的單元格的文本帶有RMB字符串,如:<font color=red>RMB</font>50.47
//截取出其中的價格
strprice = strprice.Substring(strprice.LastIndexOf(">")+1);
//將價格轉換爲double型數據
double price = double.Parse(strprice);
if (price > 50)
{
e.Row.BackColor = System.Drawing.Color.Yellow;//使用預設顏色來設置行的背景色
e.Row.ForeColor = System.Drawing.Color.FromName("#ff0000");//使用十六進制的顏色,設置前景色
}
}
}
}
//計算當前頁中所有汽車的平均價格,並在頁腳顯示
private void GetAvgPrice(GridViewRowEventArgs e)
{
//累加當前頁中的汽車的價格總和(_PriceSum)
if (e.Row.RowType == DataControlRowType.DataRow)
{
if (e.Row.RowState == DataControlRowState.Normal || e.Row.RowState == DataControlRowState.Alternate)
{
string strprice = e.Row.Cells[4].Text;//帶有RMB字符串,如:RMB50.47
strprice = strprice.Substring(strprice.LastIndexOf(">") + 1);
double price = double.Parse(strprice);
_PriceSum += price;
}
}
//根據_PriceSum計算平均價格,並在頁腳顯示
if (e.Row.RowType == DataControlRowType.Footer)
{
e.Row.Cells[4].Text = "<font color=red>RMB</font>"+(_PriceSum / GridView1.PageSize).ToString();
e.Row.Cells[4].HorizontalAlign = HorizontalAlign.Right;
}
}
//RowDataBound事件處理程序,調用上面的三個方法進行設置
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
ChangeDate(e);
HighLightCar(e);
GetAvgPrice(e);
}
執行結果:
在上面的函數中,有幾個需要重點說明的問題:
1.GridViewRowEventArgs e形參:這是在建造行對象時產生的事件數據,它裏面包含正在建造的當前行對象的信息,通過它我們可以取得正在建造的行對象和行對象中的單元格對象,並可以取得或設置這些對象相應的屬性。
2.e.Row.RowType屬性:(DataControlRowType枚舉類型)它返回正在建造的行對象的類型(如:頁眉、頁腳、數據行、分頁行等)
3.e.Row.RowState屬性:(DataControlRowState枚舉類型)它返回正在建造的行對象的狀態(如:普通狀態、交替狀態、編輯狀態、選中狀態等)
下面這段代碼,大家一定不能漏掉
if (e.Row.RowType == DataControlRowType.DataRow)
{
if (e.Row.RowState == DataControlRowState.Normal || e.Row.RowState == DataControlRowState.Alternate)
{
}
}
它代表我們的操作只對數據行起作用,不對頁眉和頁腳起作用(因爲頁眉頁腳的文本中並不包含我們需要的數據)。並且僅當數據行處理普通狀態和交替狀態時起作用,在編輯和選中狀態不是不起作用的(編輯狀態下,數據不是顯示在單元格的Text中,而是顯示在單元格的控件中的)。(車延祿)
二、超鏈接列的使用
超鏈接列也是開發過程中使用比較多的列的類型,它是在GridView的單元格中顯示超鏈接信息,在點擊超鏈接時跳轉到相應的頁面上去。
如上圖所示,由於我們Car表中的列很多,如果在一個頁面中全顯示出來會使GridView中單元格的數據變形,很影響我們的外觀。我們可以只把幾項主要信息顯示出來,然後在每一行的後面加一個超鏈接列,當點擊超鏈接列時轉到一個詳細頁面,把每一型號汽車的具體信息詳細顯示出來。
效果如下圖
汽車列表頁面
汽車詳細信息頁面
下面我們看看如何實現這種效果
第一步:向頁面中加入ObjectDataSource,GridView並配置好它們。
第二步:點擊GridView的智能菜單進入GridView字段設置頁面,如下圖所示
設置DataNavigateUrlField爲主鍵列Code
設置DataNavigateUrlFormatterString爲Default7.aspx?id={0}
設置HeaderText爲"查看"
設置Text爲"詳細"
第三步:點擊確定按鈕完成添加
這裏的屬性較多,在這裏我們一起來看一下
HeaderText:該超鏈接列的頁眉文本
FooterText:該超鏈接列的頁腳文本
Text:超鏈接列中的鏈接文字,這個屬性用來把該列所有單元格的超鏈接的文字設成相同的。
DataTextField:指定數據源的一個字段名,把該字段的內容作爲超鏈接列的超鏈接文本。如果同時設置了Text屬性和DataTextField屬性,則忽略Text屬性的設置。
DataTextFormatterString:爲綁定顯示的DataTextFied數據設置顯示格式
DataNavigateUrlField:指定數據源的一個字段名,該字段的內容作爲超鏈接列導向的網址,或者把該字段的值作爲超鏈接傳遞的參數。
DataNavigateUrlFormatterString:爲DataNavigateUrlField列設置超鏈接的導航格式。如Default7.aspx?id={0}則該列的超鏈接導航到Default7.aspx頁面,並且把DataNavigateUrlField中指定的字段值賦給id,作爲查詢字符串傳遞至Default7.aspx頁面
如果超鏈接列需要向目標頁面傳遞多個字段的值作爲參數的話,那麼請在DataNavigateUrlField中指定多個字段名並用逗號隔開,然後再在DataNavigateUrlFormatterString屬性中用"&"鏈接多個參數(如:default7.aspx?id={0}&name={1})