7.DataKeyField和DataKeys
DataKeyField是綁定的字段,DataKeys是綁定字段的綁定數(shù)據(jù)的集合。如DataKeyField="Id"DataKeys保存的就是Id字段值的集合。
DataKeyField指定數(shù)據(jù)源的鍵字段,指定的字段用于填充DataKeys集合,DataKeys集合訪問數(shù)據(jù)列表控件中每個(gè)記錄的鍵值,此集合自動用DataKeyField屬性指定的字段中的值填充。
DataKeyField是字段名,DataKeys是對應(yīng)的字段值,沒有DataKeyField就沒有DataKeys。
8.GridView的DataKeyNames屬性
DataKeyNames表示主鍵的列名,可以通過GridViewEntity.DataKeys[RowIndex]["ColumsName"]來獲取他的值,當(dāng)然它是不會顯示出來的,其實(shí)我是在一個(gè)用SqlDataSource中發(fā)現(xiàn)的,看到了有這么一個(gè)主鍵而實(shí)現(xiàn)更新,當(dāng)然在我們多層開發(fā)中也不能缺少這個(gè)。當(dāng)我們在用Template時(shí)怎么取得值呢?我們可以把那個(gè)列也設(shè)為DataKeyNames中,記得多個(gè)要用","隔開。
如果沒有設(shè)置成DataKeyNames,那只能通過GridViewEntity.Rows[RowIndex].Cell[Index].Text來得到值了,不知老兄有沒有看到一些HTML字符呢? 這個(gè)最是經(jīng)常見得了,不用擔(dān)心我們可以用HttpUnility.HtmlDecode()來解決他!
在我們使用GridView的過程中,經(jīng)常會遇到這樣的問題,我們選擇某一行進(jìn)行編輯,或選擇某一行刪除或者.......時(shí),我們需要獲取當(dāng)前行的某些信息,尤其是當(dāng)前行的主鍵信息,
主鍵信息一般不顯示在頁面,此時(shí)我們有三種方法來處理。
第一種是使用DataKeyNames,這里要重點(diǎn)介紹的。
第二種是使用按鈕的CommandArgument屬性邦定需要的信息。
第三種是最古老最通用的方法使用隱藏的方法顯示。
第一種方法:使用DataKeyNames,DataKeyNames可邦定一列,也可邦定多列
前臺:DataKeyNames="FID"綁定一個(gè)值
后臺:GridView1.DataKeys[e.Row.RowIndex].Value.ToString();
前臺:DataKeyNames="FID,FName"綁定兩個(gè)值
后臺:GridView1.DataKeys[e.Row.RowIndex].Values[0].ToString();
后臺:GridView1.DataKeys[e.Row.RowIndex].Values[1].ToString();
或者
后臺:GridView1.DataKeys[e.Row.RowIndex].Values["FID"].ToString();
后臺:GridView1.DataKeys[e.Row.RowIndex].Values["FName"].ToString();
第二種方法:是用按鈕的CommandArgument屬性邦定需要的信息。
典型的例子:下載附件列(有附件的顯示下載鏈接,無附件的顯示為空)
<asp:TemplateColumnHeaderText="附件">
<HeaderStyleWidth="7%"></HeaderStyle>
<ItemTemplate>
<asp:LinkButton id="LinkButton1"CommandName="download" CommandArgument='<%#DataBinder.eval_r(Container.DataItem,"attached_file")%>' runat="server"Visible='<%# ((DataBinder.e val_r(Container.DataItem,"attached_file").ToString()) != "")%>'>下載</asp:LinkButton>
</ItemTemplate>
</asp:TemplateColumn>
在dgHKStock_ItemCommand事件中:
if ("download" == e.CommandName)
{
mybc.SystemOverTime0();// 判斷Session是否過期
mybc.RightManage("16010500");// 判斷用戶是否有打開此網(wǎng)頁的權(quán)限
mybc.HTTP_DownloadFile(e.CommandArgument.ToString()); //取得當(dāng)前存貨信息的附件存放路徑
}
最古老最通用的方法使用隱藏的方法顯示。
<styletype="text/css">
.test{
display:none;
}
</style>
<asp:TemplateFieldHeaderText="姓名" SortExpression="name" ItemStyle-CssClass="test"HeaderStyle-CssClass="test">
<ItemTemplate>
<asp:Label ID="Label1" runat="server"Text='<%# eval_r("name") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
把隱藏列轉(zhuǎn)成模版列,通過FindControl訪問模版列的內(nèi)容:
<asp:TemplateFieldVisible="false">
<ItemTemplate>
<asp:Label runat="server"Text='<%#eval_r("id") %>'ID="lblId"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
protected voidGridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
LabellblId=GridView1.Rows[e.NewEditIndex].Cells[0].FindControl("lblId")as Label;
Response.Write(lblId.Text);
}
9.運(yùn)行錯(cuò)誤,提示說無法將類型“string”隱式轉(zhuǎn)換為“string[]”
this.GridView1.DataKeyNames= "userID";
string[] user=newstring[]{"userID"};
this.GridView1.DataKeyNames=user;
10.如何在ASP.NET中獲得RowIndex的簡單方法
為什么需要在RowCommandevent獲得RowIndex呢?通常一個(gè)Table的PK或FK并不會顯示在GridView上,而會設(shè)定在DataKeyNamesproperty,然后再RowCommandevent根據(jù)RowIndex讀出該row的PK或FK,所以第一步,必須先能在RowCommand獲得RowIndex。
ASP.NET 1.xDataGrid
在ASP.NET1.x的DataGrid,若要使用LinkButton,一樣得放在TemplateColumn內(nèi),且ItemCommandevent的e.Item.ItemIndex就可抓到RowIndex。
當(dāng)在DataGrid點(diǎn)下FirstName后,會在下方的Label顯示LastName,LastName是此例的DataKey。
<%@ImportNamespace="System.Data"%>
<%@ImportNamespace="System.Data.SqlClient"%>
<%@PageLanguage="C#"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<scriptrunat="server">
protectedvoidPage_Load(objectsender,EventArgse){
if(!IsPostBack)
DataGrid1_DataBind();
}
protectedvoidDataGrid1_DataBind(){
stringstrSQL="SELECTTOP10"+
"fname,"+
"lname"+
"FROMemployee";
SqlConnectioncon=newSqlConnection(@"DataSource=.sqlexpress;Initial
Catalog=pubs;IntegratedSecurity=True");
SqlDataAdapterda=newSqlDataAdapter(strSQL,con);
DataSetds=newDataSet();
try{
da.Fill(ds);
}
catch(Exceptionerr){
Response.Write(err.ToString());
return;
}
finally{
if((con!=null)&&(con.State==ConnectionState.Open))
con.Close();
}
DataGrid1.DataSource=ds;
DataGrid1.DataKeyField="lname";
DataGrid1.AutoGenerateColumns=false;
DataGrid1.DataBind();
}
protectedvoidDataGrid1_ItemCommand(objectsource,DataGridCommandEventArgse){
if(e.CommandName=="Select")
Label1.Text=DataGrid1.DataKeys[e.Item.ItemIndex].ToString();
}
</script>
<htmlxmlns="http://www.w3.org/1999/xhtml">
<headrunat="server">
<title>UntitledPage</title>
</head>
<body>
<formid="form1"runat="server">
<asp:DataGridID="DataGrid1"runat="server"OnItemCommand="DataGrid1_ItemCommand">
<Columns>
<asp:TemplateColumnHeaderText="FirstName">
<ItemTemplate>
<asp:LinkButtonID="LinkButton1"runat="server"CommandName="Select"
Text='<%#DataBinder.eval_r(Container.DataItem,"fname")%>'>
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:DataGrid>
<asp:LabelID="Label1"runat="server"></asp:Label>
</form>
</body>
</html>
只需在ItemCommandevent的e.Item.ItemIndex就可以輕松的抓到RowIndex。
ASP.NET 2.0GridView
ASP.NET2.0就改用SqlDataSource和GridView了,LinkButtom一樣得放在TemplateField,但GridView沒有ItemCommandevent,取而代之的是RowCommand event。
<%@PageLanguage="C#"%>
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<scriptrunat="server">
protectedvoidPage_Load(objectsender,EventArgse){
if(!IsPostBack)
GridView1_DataBind();
}
protectedvoidGridView1_DataBind(){
SqlDataSource1.ConnectionString=@"DataSource=.sqlexpress;Initial
Catalog=pubs;IntegratedSecurity=True";
SqlDataSource1.SelectCommand="SELECTTOP10"+
"fname,"+
"lname"+
"FROMemployee";
GridView1.DataSourceID=SqlDataSource1.ID;
GridView1.DataKeyNames=newstring[]{"lname"};
GridView1.AutoGenerateColumns=false;
}
protectedvoidGridView1_RowCommand(objectsender,GridViewCommandEventArgse){
if(e.CommandName=="Select"){
introwIndex=((GridViewRow)((LinkButton)e.CommandSource).NamingContainer).RowIndex;
Label1.Text=GridView1.DataKeys[rowIndex].Value.ToString();
}
}
</script>
<htmlxmlns="http://www.w3.org/1999/xhtml">
<headrunat="server">
<title>UntitledPage</title>
</head>
<body>
<formid="form1"runat="server">
<div>
<asp:GridViewID="GridView1"runat="server"OnRowCommand="GridView1_RowCommand">
<Columns>
<asp:TemplateFieldHeaderText="FirstName">
<ItemTemplate>
<asp:LinkButtonID="LinkButton1"runat="server"CommandName="Select"
Text='<%#eval_r("fname")%>'></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</div>
<asp:LabelID="Label1"runat="server"></asp:Label>
<asp:SqlDataSourceID="SqlDataSource1"runat="server"></asp:SqlDataSource>
</form>
</body>
</html>
CommandSource傳的是按下去的LinkButton,不過由于傳回的是Object,就得自行轉(zhuǎn)成LinkButton,但由于我們想知道的是RowIndex,而LinkButton是包含在GridViewRow內(nèi),所以透過NamingContainer傳回目前的GridViewRow,但傳回的是Control,所以需在轉(zhuǎn)成GridViewRow后才能有RowIndexproperty。
GridView是DataGrid的繼承人,但不少寫法和DataGrid并不一樣,GridView很多地方比DataGrid更強(qiáng)更好用,但這個(gè)例子卻發(fā)現(xiàn)GridView比DataGrid麻煩些。
11.gridview使用TemplateField中的LinkButton時(shí)如何在RowCommand事件中找到當(dāng)前行index的方法
ASP.NET2.0中的GRIDVIEW控件真是非常奇怪,不知道MS是怎么考慮的,在GRIDVIEW里,行索引被放在了CommandArgument里面,而不是像DataGrid那樣可以利用this.MyDataGrid.DataKeys[e.Item.ItemIndex].ToString()方便的取出主鍵值,同時(shí)我們注意到,如果使用默認(rèn)的CommandField,<asp:CommandFieldShowDeleteButton="True" ShowEditButton="True"/>則可以在RowCommand中使用如下代碼取出行號:
protected voidGridView1_RowCommand(object sender, GridViewCommandEventArgse)
{
//編輯按扭
if (e.CommandName== "Edit")
{
//設(shè)置編輯行高亮顯示
this.GridView1.EditRowStyle.BackColor= Color.FromName("#F7CE90");
//string
index=this.GridView1.DataKeys[Convert.ToInt32(e.CommandArgument)].Value.ToString();
int index =Convert.ToInt32(e.CommandArgument);
GridViewRow row =GridView1.Rows[index];
string xh3 =row.Cells[3].Text;
}
}
但問題是,CommandField的可操控性是很底的,我們一般習(xí)慣于使用模版列來訂制操作按鈕,如下:
<asp:TemplateFieldHeaderText="操作" ShowHeader="False">
<EditItemTemplate>
<asp:LinkButtonID="LinkButton1" runat="server" CausesValidation="True"CommandName="Update"Text="更新"></asp:LinkButton>
<asp:LinkButtonID="LinkButton2" runat="server" CausesValidation="False"CommandName="Cancel"Text="取消"></asp:LinkButton>
</EditItemTemplate>
<ItemTemplate>
<asp:LinkButtonID="LinkButton1" runat="server" CausesValidation="False"CommandName="Edit" Text="編輯"></asp:LinkButton>
<asp:LinkButtonID="LinkButton2" runat="server" CausesValidation="False"CommandName="Select"Text="選擇"></asp:LinkButton>
<asp:LinkButtonID="LinkButton3" runat="server" CausesValidation="False"CommandName="Delete" Text="刪除"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
隨之而來,問題出現(xiàn)了,運(yùn)行報(bào)錯(cuò):輸入字符串的格式不正確,Convert.ToInt32(e.CommandArgument)中e.CommandArgument轉(zhuǎn)換為字符串為空。當(dāng)我們把CommandField轉(zhuǎn)換為模版列時(shí),默認(rèn)的CommandArgument屬性丟失了?。。?/p>
思考了兩天,翻閱了網(wǎng)上的資料,最后在MSDN文檔中發(fā)現(xiàn),呈現(xiàn)GridView 控件之前,必須先為該控件中的每一行創(chuàng)建一個(gè) GridViewRow 對象。在創(chuàng)建 GridView控件中的每一行時(shí),將引發(fā) RowCreated事件。這使我們可以提供一個(gè)這樣的事件處理方法,即每次發(fā)生此事件時(shí)都執(zhí)行一個(gè)自定義例程(如在行中添加自定義內(nèi)容,當(dāng)然也可以添加e.CommandArgument屬性為模版列里的LinkButton)。
GridViewRowEventArgs對象將被傳給事件處理方法,隨之我們可以訪問正在創(chuàng)建的行的屬性。若要訪問行中的特定單元格,可以使用GridViewRowEventArgs 對象的 Cells 屬性。使用 RowType屬性可確定正在創(chuàng)建的是哪一種行類型(標(biāo)題行、數(shù)據(jù)行等等)。
好了,原來我們可以利用RowCreated事件來為模版列中LinkButton寫入CommandArgument事件。
下面的代碼示例演示如何使用RowCreated 事件將正在創(chuàng)建的行的索引存儲在該行中所包含的 LinkButton 控件的 CommandArgument屬性中。這允許您確定在用戶單擊 LinkButton 控件按鈕時(shí)包含該控件的行的索引。
///<summary>
///為模版列LinkButton寫入CommandArgument事件
///</summary>
///<paramname="sender"></param>
///<paramname="e"></param>
protected voidGridView1_RowCreated(object sender, GridViewRowEventArgse)
{
if (e.Row.RowType== DataControlRowType.DataRow)
{
/ Retrieve theLinkButton control from the first column.
LinkButtonLinkButton1 =(LinkButton)e.Row.FindControl("LinkButton1");
// Set theLinkButton's CommandArgument property with the row'sindex.
LinkButton1.CommandArgument= e.Row.RowIndex.ToString();
}
}
好了,其余的代碼不變,在GridView1_RowCommand中的代碼不變.
比如再一個(gè)單元格中要加入兩個(gè)按鈕:
.aspx頁面:
<asp:TemplateFieldHeaderText="導(dǎo)航序號" ShowHeader="False">
<ItemTemplate>
<asp:LabelID="Label3" runat="server" Text='<%#eval_r("Modsort")%>'></asp:Label>
<asp:ImageButtonID="ImageButton1" runat="server"
ImageUrl="/Manager/enterpriseManager/Mod/Images/up.png"Height="18px"
Width="17px"CausesValidation="false" CommandName="up" Text="up"/>
<asp:ImageButtonID="ImageButton2" runat="server"
ImageUrl="/Manager/enterpriseManager/Mod/Images/down.png"Height="18px"
Width="17px"CausesValidation="false" CommandName="down" Text="down"/>
</ItemTemplate>
<HeaderStyleBackColor="#C00000" />
<ItemStyleHorizontalAlign="Center" />
</asp:TemplateField>
cs文件:
在RowCreated事件里面(注意這里很重要)
protected voidGridView_RowCreated(object sender, GridViewRowEventArgse)
{
if (e.Row.RowType== DataControlRowType.DataRow)
{
ImageButtonImageButton1 = e.Row.FindControl("ImageButton1") asImageButton;
ImageButton1.CommandArgument= e.Row.RowIndex.ToString();
ImageButtonImageButton2 = e.Row.FindControl("ImageButton2") asImageButton;
ImageButton2.CommandArgument= e.Row.RowIndex.ToString();
}
}
在RowCommand事件里面:
protected voidmod_RowCommand(object sender, GridViewCommandEventArgse)
{
if (e.CommandName== "up")
{
ClientScript.RegisterStartupScript(GetType(),"","<script>alert('我要UP!');</script>");
}
if(e.CommandName=="down")
{
ClientScript.RegisterStartupScript(GetType(),"","<script>alert('我要DOWN!');</script>");
}
}
12.實(shí)現(xiàn)GrdView分頁的功能
操作如下:
1、更改GrdView控件的AllowPaging屬性為true。
2、更改GrdView控件的PageSize屬性為任意數(shù)值(默認(rèn)為10)
3、更改GrdView控件的PageSetting->Mode為Numeric等(默認(rèn)為Numeric)該屬性為分頁樣式。
GridView屬性設(shè)置好了,從頁面上也能看到分頁樣式。
現(xiàn)在開始實(shí)現(xiàn)分頁的功能:
1、在<<asp:GridViewID=......>后添加,OnPageIndexChanging="GridView1_PageIndexChanging"
2、在對應(yīng)的aspx.cs中添加:
protected void GridView1_PageIndexChanging(object sender,GridViewPageEventArgs e)
{
GridView1.PageIndex = e.NewPageIndex;
InitPage(); //重新綁定GridView數(shù)據(jù)的函數(shù)
}
3、
GridView1.PageIndex= e.NewPageIndex;
完了之后再重新綁定一下GridView就好了。
13RowDataBound事件
在創(chuàng)建gridView控件時(shí),必須先為GridView的每一行創(chuàng)建一個(gè)GridViewRow對象,創(chuàng)建每一行時(shí),將引發(fā)一個(gè)RowCreated事件;當(dāng)行創(chuàng)建完畢,每一行GridViewRow就要綁定數(shù)據(jù)源中的數(shù)據(jù),當(dāng)綁定完成后,將引發(fā)RowDataBound事件。如果說我們可以利用RowCreated事件來控制每一行綁定的控件,那么我們同樣可以利用RowDataBound事件來控制每一行綁定的數(shù)據(jù),也就是讓數(shù)據(jù)如何呈現(xiàn)給大家。
還舉同樣的例子,在數(shù)據(jù)表中,存在性別列,上面我們用DropListDown控件的DataBounding來表示出了中文的性別,但是畢竟不太美觀,我們現(xiàn)在可以利用Label控件和RowDataBound事件來實(shí)現(xiàn)完美的中文性別顯示。RowDataBound,
首先,還是把性別列,設(shè)置為模板列,并添加一個(gè)Label控件,將Label控件綁定到數(shù)據(jù)源的性別段,然后我們在GridView控件屬性的事件列表中雙擊RowDataBound,生成如下事件:
Example:
protected void GridView1_RowDataBound(object sender,
GridViewRowEventArgs e)
{
//判斷當(dāng)前行是否是數(shù)據(jù)行
if (e.Row.RowType == DataControlRowType.DataRow)
{ //用FindControl方法找到模板中的Label控件
Label lb1= (Label)e.Row.FindControl("Label1");
//因?yàn)镽owDataBound是發(fā)生在數(shù)據(jù)綁定之后,所以我們可以
//判斷Label綁定的數(shù)據(jù),如果是True,就更改其text屬性為男
if (lb1.Text== "True")
lb1.Text = "男";
else
lb1.Text = "female";
}
}
14SQL數(shù)據(jù)庫里兩個(gè)‘一對多’的表綁到gridview里
比如:
表1
ID 姓名
1 張三
2 李四
3 王五
表2
RID 科目 分?jǐn)?shù)
1 數(shù)學(xué) 87
1 語文 78
2 數(shù)學(xué) 67
2 語文 97
顯示成
1 張三 數(shù)學(xué)87&語文78
2 李四 數(shù)學(xué)67&語文97
create table studentInfo
(
sIdint,
sNamevarchar(20)
)
insertinto studentInfo([sId],[sName])values(1,'張三')
insert into studentInfo([sId],[sName])values(2,'李四')
insert into studentInfo([sId],[sName])values(3,'王五')
select* from [studentInfo]
--drop table studentInfo
create table scoreInfo
(
rIdint,
pNamevarchar(20),
scoreint
)
insertinto scoreInfo([rId],[pName],[score])values(1,'數(shù)學(xué)',87)
insert into scoreInfo([rId],[pName],[score])values(1,'語文',78)
insert into scoreInfo([rId],[pName],[score])values(2,'數(shù)學(xué)',67)
insert into scoreInfo([rId],[pName],[score])values(2,'語文',97)
select* from scoreInfo
--drop tablescoreInfo
select[sId],[sName],(
select
'數(shù)學(xué)'+ltrim(str(isnull(sum(case[pName]when '數(shù)學(xué)'then [score]end),0)))
+'&語文'+ltrim(str(isnull(sum(case[pName]when '語文'then [score]end),0)))
from [scoreInfo] scwhere st.[sId]=sc.[rId])
from [studentInfo] st
1張三
2李四
3王五
1數(shù)學(xué)87
1語文78
2數(shù)學(xué)67
2語文97
1張三數(shù)學(xué)87&語文78
2李四數(shù)學(xué)67&語文97
3王五數(shù)學(xué)0&語文0
愛華網(wǎng)



