網(wǎng)站建設(shè)時(shí)經(jīng)常需要用到gridview獲取隱藏列的值的方法,這個(gè)問(wèn)題是比較常見(jiàn)的,網(wǎng)上也有不少類似文章,最近做項(xiàng)目也遇到這個(gè)問(wèn)題,這里在自己分析基礎(chǔ)上,結(jié)合實(shí)際問(wèn)題,總結(jié)這一問(wèn)題的幾種解決方案。
問(wèn)題提出:在使用GridView控件時(shí)候,往往需要對(duì)某一列進(jìn)行隱藏,而在后臺(tái)代碼中,有時(shí)卻又需要這個(gè)隱藏 列的值來(lái)進(jìn)行一些別的操作,比如我就遇到一個(gè)實(shí)際問(wèn)題:控件GridView的ID為GV,其中某一列X(X為索引號(hào))的所有單元格的背景顏色,需要根據(jù) 另一列Y(Y為索引號(hào))的數(shù)值來(lái)確定,而Y這一列是我不想讓用戶看到的,所以需要隱藏Y列,可是問(wèn)題出來(lái)了,用如下方式設(shè)置了列的不可見(jiàn):
GV.Columns[Y].Visible=false;
卻發(fā)現(xiàn)之后在取這一列中單元格的值時(shí),始終是為空,也就是說(shuō)這種隱藏方式后,無(wú)法訪問(wèn)單元格的數(shù)值了。另外,用這個(gè)方法在特定問(wèn)題時(shí)還有另外一個(gè)弊端,這個(gè)在解決方法2中會(huì)提到。
問(wèn)題分析:GridView是Asp.net 2.0中增加了一個(gè)新的數(shù)據(jù)綁定控件,其目的用來(lái)取代Asp.net1.x中的DataGrid控件,以前用DataGrid時(shí)候,上述問(wèn)題是不存在的, 即使設(shè)置了列的隱藏,也可以進(jìn)行訪問(wèn)。通過(guò)網(wǎng)上找一些類似的問(wèn)題,可以知道,如果把某列的Visible屬性設(shè)false,則不會(huì)進(jìn)行數(shù)據(jù)綁定,也就是說(shuō) 無(wú)法直接從GridView中取到這個(gè)列內(nèi)的數(shù)值。因此,這就需要既要用別的方式來(lái)隱藏列,又要取到隱藏列的值。
解決方法:
1.隱藏列前獲取數(shù)據(jù)
看這樣一個(gè)例子(以下均以此為例):用戶選擇一些查詢條件后,點(diǎn)擊“查詢”按鈕。后臺(tái)需要根據(jù)每行中第六列的值是否為1,來(lái)設(shè)置第三個(gè)單元格的背景色為紅色。
這種方法中,后臺(tái)是在按鈕的Click事件中,去數(shù)據(jù)庫(kù)取記錄,然后得到DataTable,最后將它綁定到GridView中。如果我們需要在 GridView的RowDataBound事件中取隱藏列的值,則用Visible屬性來(lái)設(shè)置某一列為隱藏,是沒(méi)問(wèn)題的。如下代碼:
protected void Btn_Query_Click(object sender, EventArgs e)
{
DataTable dt = new DataTable(); dt=ConstructActiveDataTable();//一個(gè)取記錄的方法
GV.DataSource = dt; GV.DataBind(); GV.Columns[5].Visible = false;//設(shè)置第6列為隱藏
}
protected void GV_UpdateData_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
if (e.Row.Cells[5].Text.ToString() == "1")//當(dāng)行中的第六個(gè)單元格的值為1時(shí)(第六列為隱藏哦)
{
e.Row.Cells[2].BackColor = System.Drawing.Color.Red;//設(shè)置行中第三個(gè)單元格背景色為紅色
}
}}
為什么這樣就可以了呢?其實(shí)是利用了在隱藏列之前就把數(shù)值取到了,然后最后再隱藏列。因?yàn)樵贑lick事件中,當(dāng)GV.DataBind()后,不 是執(zhí)行了GV.Columns[5].Visible = false,而是立刻觸發(fā)了RowDataBound事件,等執(zhí)行完了此事件,才繼續(xù)回去執(zhí)行的隱藏列的代碼。因此,這類特定問(wèn)題中,只要利用事件或函數(shù) 調(diào)用的順序關(guān)系,即可避免無(wú)法取值的問(wèn)題。
當(dāng)然,這一解決方案并非通用,它對(duì)代碼執(zhí)行順序有要求。
2.分別隱藏列中每個(gè)單元格
有些時(shí)候,我們不想用上面那種手動(dòng)方式(DataBind())來(lái)綁定GridView了,而是使用一些已有的數(shù)據(jù)源控件,比 如:objectdatasource控件。將GridView的DataSourceID指定為objectdatasource控件的ID,則 objectdatasource控件指定其SelectMethod屬性為一個(gè)返回類型是集合類型的函數(shù)(比如返回DataTable),就會(huì)在后臺(tái)自 動(dòng)去調(diào)用這個(gè)函數(shù)并綁定(具體方法就不說(shuō)了)。
那么依然是上面那個(gè)應(yīng)用,根據(jù)隱藏列值來(lái)設(shè)置另一個(gè)單元格的背景顏色,上面那個(gè)順序就不可能實(shí)現(xiàn)了,因?yàn)轭愃朴贒ataBind的綁定是隱式執(zhí)行 的,雖然他可能也是綁定后立刻觸發(fā)RowDataBound事件,然后回去執(zhí)行剩余代碼,但是我們不能在剩余代碼中再如上面的插入設(shè)置列隱藏的代碼。因 此,依靠控制代碼順序來(lái)實(shí)現(xiàn)不太可能了,這是第一個(gè)問(wèn)題。另外,還有一個(gè)問(wèn)題(問(wèn)題提出中所指),就是這個(gè)控件比較 怪,如果你在用objectdatasource綁定后,設(shè)置了一次列的Visible,那么objectdatasource就會(huì)重新去綁定一次數(shù)據(jù), 那么如果隱藏10個(gè)列,豈不是要去重新從數(shù)據(jù)庫(kù)等數(shù)據(jù)源重復(fù)讀十遍數(shù)據(jù),這個(gè)性能上是不可接受的。
鑒于這兩個(gè)原因,必須有別的方法來(lái)隱藏列。
既然列是由單元格形成的,那么一一隱藏單元格肯定也能達(dá)到隱藏的效果,但是隱藏后能否獲取到其值呢,經(jīng)過(guò)驗(yàn)證,確實(shí)可以。不過(guò)要注 意,F(xiàn)ooter,Header和DataRow中的單元格都需要隱藏哦,否則表格就錯(cuò)位了。隱藏的代碼放哪里都可以,建議放在RowDataBound 事件中,這樣每生成一行就去隱藏相應(yīng)列即可。
protected void GV_UpdateData_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header || //如果設(shè)置gridview不顯示Header,就不寫這個(gè)(否則報(bào)錯(cuò))
e.Row.RowType == DataControlRowType.DataRow ||
e.Row.RowType == DataControlRowType.Footer) //如果設(shè)置gridview不顯示Footer,就不寫這個(gè)(否則報(bào)錯(cuò))
{
e.Row.Cells[5].Visible=false;//設(shè)置每一行中第六個(gè)單元格為隱藏,達(dá)到隱藏第六列的目的
}
if (e.Row.RowType == DataControlRowType.DataRow)
{
if (e.Row.Cells[5].Text.ToString() == "1")//即使隱藏了,依然可以訪問(wèn)到數(shù)值哦
{
e.Row.Cells[2].BackColor = System.Drawing.Color.Red;//設(shè)置行中第三個(gè)單元格背景色為紅色
}
}
}
依然有人認(rèn)為這代碼不夠好,有些人不喜歡用事件,另外也擔(dān)心性能問(wèn)題,畢竟每一行都要觸發(fā)這個(gè)事件。
3.利用新的屬性DataKeys和DataKeyNames
事實(shí)上,微軟所作的考慮更加周全。針對(duì)GridView無(wú)法提供行主鍵的問(wèn)題,它提供了兩個(gè)全新的屬性:DataKeys和DataKeyNames!其SDK中的描述如下:
DataKeyNames:獲取或設(shè)置一個(gè)數(shù)組,該數(shù)組包含了顯示在 GridView 控件中的項(xiàng)的主鍵字段的名稱。
DataKeys:獲取一個(gè) DataKey 對(duì)象集合,這些對(duì)象表示 GridView 控件中的每一行的數(shù)據(jù)鍵值。
也就是說(shuō),利用DataKeyNames,可以設(shè)置一個(gè)多個(gè)列,用于作為行的主鍵字段(這里用主鍵其實(shí)不太合適,因?yàn)橹禃r(shí)允許重復(fù)的),之后利用 DataKeys舊可以訪問(wèn)這些列的值了。因此,利用這兩個(gè)新屬性,我們就可以繼續(xù)使用利用列的Visible屬性設(shè)置來(lái)隱藏列的同時(shí),又可以訪問(wèn)隱藏列 的值了。方法如下:
GV.Columns[5].Visible = false;//設(shè)置第6列為隱藏
//只需要在設(shè)置列為隱藏的地方多加一段代碼:
GV.DataKeyNames = new string[] { "stateid_O2" };
//假設(shè)第六列的列名為stateid_O2
protected void GV_UpdateData_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (GridView_UpdateData.DataKeys[e.Row.DataItemIndex]["stateid_O2"].ToString() == "1")
//利用這個(gè)DataKeys屬性來(lái)訪問(wèn)隱藏列的值
{
e.Row.Cells[2].BackColor = System.Drawing.Color.Red;//設(shè)置行中第三個(gè)單元格背景色為紅色
}
}
4.利用客戶端代碼來(lái)隱藏列
實(shí)際上,我們上面都是在服務(wù)器端利用各種方法來(lái)隱藏列了,那么這種方法就是服務(wù)器端不對(duì)列的可見(jiàn)性進(jìn)行設(shè)置,那么顯然就不存在無(wú)法取值的問(wèn)題了,那 么又要讓用戶不看到某些列,這就需要客戶端的代碼css來(lái)實(shí)現(xiàn)隱藏效果了??梢詮纳厦娣椒ㄍ茖?dǎo)出,既可以用css直接隱藏列,也能通過(guò)隱藏列的單元格來(lái)實(shí) 現(xiàn)。首先需要一個(gè)css:
<style type="text/css">
.hidden { display:none;}
</style>
如果GridView的列是事先確定,也就是通過(guò)設(shè)計(jì)器來(lái)添加的,那么只需要在設(shè)計(jì)時(shí),將相應(yīng)列的FootStyle,HeaderStyle,ItemStyle的CssClass屬性為“hidden” 即可。
當(dāng)然,如果列是動(dòng)態(tài)的,或者隱藏哪一列只有在綁定后才能確定,那么就必須在后臺(tái)設(shè)置css。設(shè)置有兩種方法:
一種是設(shè)置列的css:
protected void GridView_UpdateData_RowDataBound(object sender, GridViewRowEventArgs e)
{
GV.Columns[5].HeaderStyle.CssClass = "hidden";
GV.Columns[5].ItemStyle.CssClass = "hidden";
GV.Columns[5].FooterStyle.CssClass = "hidden";
}
另一種是設(shè)置單元格的css:
protected void GV_UpdateData_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header || //如果設(shè)置gridview不顯示Header,就不寫這個(gè)(否則報(bào)錯(cuò))
e.Row.RowType == DataControlRowType.DataRow ||
e.Row.RowType == DataControlRowType.Footer) //如果設(shè)置gridview不顯示Footer,就不寫這個(gè)(否則報(bào)錯(cuò))
{
e.Row.Cells[5].CssClass = "hidden";
}
}
總結(jié):
第一種方法不太通用,要求在隱藏列前就去訪問(wèn)值,這個(gè)是一個(gè)約束條件。第二種通過(guò)服務(wù)器端隱藏列中每個(gè)單元格來(lái)實(shí)現(xiàn)效果,效率一般;第三種應(yīng)該是標(biāo) 準(zhǔn)方式,利用新的屬性來(lái)達(dá)到目的,需要熟悉他的用法;最后一種是在客戶端進(jìn)行隱藏,但是數(shù)據(jù)還是傳到客戶端了,如果不介意這樣一點(diǎn)多出的數(shù)據(jù)量,這個(gè)應(yīng)該 最容易理解和使用。