我这有篇孟宪会写的讨论DataGrid的文章《创建功能完备的DataGrid》,来个借化献佛。  你对ASP.NET的DataGrid的编辑功能是不是感到很失望呢?我们就在本文里向你介绍一种利用.NET基本类型库构建自己的全功能的DataGrid。在基于WEB的应用中,直接编辑数据,并更新到数据库可以得到一种意想不到的效果。ASP.NET向我们提供了许多基类,以帮助我们创建我们自己的全功能的DataGrid。本文就利用System.Text类创建我们的Datadrid,然后利用System.Data.SqlClient类和数据库交互,在使用之前,必须先把它们导入到应用程序中。 
我们首先创建一个基本表单,上面放两个控件,一个是更新按钮,另一个是显示数据的容器。利用高效的StringBuilder类来生成数据网格的HTML字符串。先看看得到数据的代码: private DataSet getDS() 

System.Data.SqlClient.SqlConnection myConn; 
string conn = "server=(localhost)\\NetSDK;database=Northwind;Trusted_Connection=yes"; 
myConn = new System.Data.SqlClient.SqlConnection(conn); 
ds = new DataSet(); 
ds.CaseSensitive = true; 
SqlCommand sqlcmd = new System.Data.SqlClient.SqlCommand(); 
sqlcmd.Connection = myConn; 
sqlcmd.CommandText = "Select CustomerID,CompanyName, ContactName,ContactTitle from Customers"; 
da = new SqlDataAdapter(sqlcmd); 
SqlCommandBuilder SCB = new SqlCommandBuilder(da); 
da.SelectCommand = sqlcmd; 
da.TableMappings.Add("Table","Customers"); 
da.Fill(ds); 
return ds; 
} DataSet返回数据库中数据的列和行,就象一张表格。为了填充网格,我们必须先写出所需的HTML,构建不同的列对象,然后遍历整个数据表,利用StringBuilder类产生出页面表格的HTML代码。 
private void writeGrid() 

DataTable dt = getDS().Tables[0]; 
DataRow dr; 
StringBuilder sb = new StringBuilder(); 
//HTML表格开始 
sb.Append ("<table class='tblDataGrid' borderColor='gray' cellSpacing='1' 
cellPadding='1' border='1' width='825px' >"); 
int col = 0; //列数变量 for(int i=0; i<dt.Rows.Count-1;i++) 

dr = dt.Rows[i]; 
col=0; 
sb.Append ("<tr class='trDataGrid' name=tr" + i + " id=tr" + i + " >"); 
//input文本框 
sb.Append("<td class='tdDataGrid' style=width:185px nowrap >"); 
sb.Append("<input class='txtDataGrid' type=text Id='df" + i + "-" + col + "' 
Name='df" + i + "-" + col + "' value='" + dr[col].ToString() + "' 
size='20' onChange=rowChange('" + i + "')></input> "); 
sb.Append("</td>"); 
col++; 
sb.Append("<td class='tdDataGrid' style=width:185px nowrap >"); 
sb.Append("<input class='txtDataGrid' type=text Id='df" + i + "-" + col + "' 
Name='df" + i + "-" + col + "' value='" + dr[col].ToString() + "' 
size='20' onChange=rowChange('" + i + "')></input> "); 
sb.Append("</td>"); 
col++; 
sb.Append("<td class='tdDataGrid' style=width:185px nowrap >"); 
sb.Append("<input class='txtDataGrid' type=text Id='df" + i + "-" + col + "' 
Name='df" + i + "-" + col + "' value='" + dr[col].ToString() + "' 
size='20' onChange=rowChange('" + i + "')></input> "); 
sb.Append("</td>"); 
col++; 
sb.Append("<td class='tdDataGrid' style=width:185px nowrap >"); 
sb.Append("<input class='txtDataGrid' type=text Id='df" + i + "-" + col + "' 
Name='df" + i + "-" + col + "' value='" + dr[col].ToString() + "' 
size='20' onChange=rowChange('" + i + "')></input> "); 
sb.Append("</td>"); 
col++; 
//隐藏表单域,保存要更新的数据行的状态 
sb.Append("<input type=hidden id=hid'" + i +"' Name='hid" + i+ "' 
value='existing' >"); 
//关闭行标记 
sb.Append("</tr>"); 

sb.Append("</table>"); 
//显示出表格 
Output.InnerHtml = sb.ToString(); 
} 在上面的代码中,我们以数据的行、列位置来命名网格元素,这样可以方便我们对网格进行操作,也可以避免担心列数量的多少和列名字的变化。现在,我们已经创建了一个数据网格(DataGrid),并且创建了控制元素,根据创建方式的不同,这些控制元素既可以是基于客户端的,也可以是基于服务器端的,文本框的OnChange事件调用rowChange函数,来更新每行隐藏表单域的值。rowChange函数如下: function rowChange(element) 

eval("document.frmMain.hid" + element + ".value = 'update'"); 
} 为了把我们更新过的数据写回数据库,我们只需要遍历那些隐藏表单域的值改变了那些行。利用DataTable的Select方法得到DataSet中变化的行,并把更新的数据写到DataSet。 private void Update() 

//创建DataTable 
DataTable udt = getDS().Tables["Customers"]; 
DataRow[] dr; 
//遍历表单元素 
int row=0;//行数 
while (Request.Form["hid" + row] != null) 

//如果有数据更新,就进行更新操作 
if (Request.Form["hid" + row] == "update") 

int col=0;//列数 //找到变化的行,并更新DataTable 
string strExp = "CustomerID = '" + Request.Form["df" + row + "-" + col]+"'"; 
dr = udt.Select(strExp); 
//更新开始 
dr[0].BeginEdit(); 
dr[0]["CustomerID"]= Request.Form["df" + row + "-" + col]; 
col++; 
dr[0]["CompanyName"] = Request.Form["df" + row + "-" + col ]; 
col++; 
dr[0]["ContactName"] = Request.Form["df" + row + "-" + col]; 
col++; 
dr[0]["ContactTitle"] = Request.Form["df" + row + "-" + col]; 
dr[0].EndEdit(); 

row++; //行数加一 

} 然后,我们调用DataAdapter的Update方法,把更新后的数据写回到数据库。注意上面的代码:当我们创建DataSet时,我们使用了SqlCommandBuilder对象,如果我们设定了SqlDataAdapter的selectCommandProperty,SqlCommandBuilder对象会自动产生单个表的Transact-SQL语句。 
private void writeChanges() 

da.Update(ds, "Customers"); 
} 一旦我们要更新的数据写回到了数据库,我们就可以调用getDataGrid函数来重新显示变化的DataGrid。 
希望本文在如何使用不同的ASP.NET提供的类来创建全功能的DataGrid上会给你一些启发。

解决方案 »

  1.   

    可以自定义服务器控件对其进行扩展,不过难度比较大,老实说自己也不懂。目前DataGrid控件提供的功能已经相当强大,配合一些技巧完全可以满足大多数的要求
      

  2.   

    我自我感觉DataGrid已经很好用了,越用越觉得高深:)
      

  3.   

    如果组合起来的话,其实可可以做出很强大的功能,一个控件总不能满足所有的要求,当然要看自己怎么组合了,要看自己能否灵活应用了,我看过一本台湾人写的.NET方面的书(BETA1),他就在缺少某些方法、属性的情况下,做出了比较强大的功能。