[翻译]用DataSource控件以外的方法为GridView提供数据
译序:此文章是今天在http://www.asp.net首页发现的,详细内容地址是http://www.dotnetbips.com/articles/displayarticle.aspx?id=511,作者Bipin Joshi。题目为Working with GridView without using Data Source Controls。
本文是根据原文的意思加自己的理解来翻译的,这段时间自己翻译过几篇其它的文章,发现对于有些地方的翻译真的就不能按照英文的愿意来,这也可能是文化差异的不同,所以我每篇翻译都强调是“按照自己的理解”来翻译,而且,是在保留作者原文的意思的基础之上。
介绍:
大多数的文章和演练都是介绍如何用DataSource控件来配合GridView来工作的。当一个GridView被指定到一个DataSource控件的时,系统就会自动完成其分页和排序的功能,而我们基本上是不用写一行代码的。然而,我们也会碰到直接把DataView和DataTable作为GridView绑定的对象的时候。幸运的是,GridView是可以用DataSource控件以外的方法来绑定数据的。但是需要开发人员敲额外的一些代码,而你对ASP.NET1.X的DataGrid很熟悉的话,就会发现其过程是很象的。本文我们将来完成直接用DataView(或者DataTable)绑定到GridView如何操作的,并且在此基础上实现分页和编辑等功能。
示例:雇员列表
我们用Northwind数据库的Employees表来做这个示例。在VS2005里新建一个站点,然后创建一个webform,拖拽一个GridView控件到此页面上。用下图的方法为GridView填加三个BoundFields和一个CommandField。
按照如下的表来设置各BoundField的属性
BoundField |
HeaderText |
DataField |
ReadOnly |
Employee ID |
Employee ID |
EmployeeID |
true |
First Name |
First Name |
FirstName |
false |
Last Name |
Last Name |
LastName |
false |
进入到codebehind页(也可能是code file),填加如下的代码到Page_Load事件:
{
if(!IsPostBack)
{
BindGrid();
}
}
然后,我们让页面在第一次显示的时候调用BindGrid()方法。这个方法是我们自定义的方法,后面我们将介绍它的具体实现。这个方法实际上是让一个DataView绑定到一个GridView上。而这个DataView里面是Employees表里的所有记录。
实现分页:
首先需要把GridView的AllowPaging属性设置为True,这样我们才可以实现分页的功能。然后我们把PageSize属性设置成3。这里有两个和分页有关的方法,它们分贝是:
·PageIndexChanging
·PageIndexChanged
第一个方法是在当前页的这个属性改变的时候被触发的,第二个方法是这个属性已经被更改以后触发的。而前一个方法你是可以在分页的时候终止这个(分页)操作的。
在GridView的PageIndexChanging事件里我们写如下的代码:
(object sender, GridViewPageEventArgs e)
{
GridView1.PageIndex = e.NewPageIndex;
BindGrid();
}
PageIndexChanging事件句柄里接收一个GridViewPageEventArgs类型的参数。这个参数通过一个叫做NewPageIndex的属性来获得用户选择的新页的页码。我们再次调用BindGrid()方法把GridView的PageIndex的属性设置成新页码。GridView就会把相应的内容显示出来。下面的截图是GridView实现分页以后的效果
实现排序:
实现排序的方法相对来说就要多做一些工作。首先,需要把GridView的AllowSorting属性设置成True,然后,我们要给需要进行排列的BoundField列上设置SortExpression属性.当你给相应的列设置好这个属性以后你就会发现这个列的头边成了一个可点击的Link button.单击它会触发如下的两个事件:
·Sorting
·Sorted
和分页方法一样这两个方法是有前后区别的。而Sorting事件也同样允许你取消这个(排序)动作。
排序事件的句柄接收一个GridViewSortEventArgs类型的参数。GridViewSortEventArgs类有三个重要的属性。SortExpression属性提供先前你指定的排序表达式。SortDirection属性描述是采用升序排序还是降序排序。着儿歌属性在你用自己创建的列表里排序是没什么用的,但是,当你用DataSource控件来为GridView做数据源的话它会为你自动指定排序的方法并且你可以通过通过这个属性利用get或set的方法指定排序的方向。
既然我们不是用DataSource控件来作为数据源那么我们需要自己来写排序的事件。我们用如下的方法来存储一个ViewState变量,填加如下代码到Sorting事件中。
GridViewSortEventArgs e)
{
ViewState["sortexpression"] = e.SortExpression;
if (ViewState["sortdirection"] == null)
{
ViewState["sortdirection"] = "asc";
}
else
{
if (ViewState["sortdirection"].ToString() == "asc")
{
ViewState["sortdirection"] = "desc";
}
else
{
ViewState["sortdirection"] = "asc";
}
}
BindGrid();
}
这里我们用一个sortexpression的ViewState变量来存储SortExpression属性。我们需要在BindGrid()方法里使用这个变量来让排序在所有情况下都能正确进行。同样我们也用一个叫做sortdirection的ViewState变量来存储当前的排序方式。最后,我们调用DataBind()方法来把DataView里排序后的数据绑定给此数据网格。
下图是实现排序以后的效果
实现编辑功能:
为了能在GridView里编辑记录我们加入了一个CommandFields到GridView里,默认情况下你会看到它是一个title属性为edit的link button.当我们单击它以后触发RowEditing事件并且编辑按钮变成了“更新”和“取消”按钮。单击“更新”按钮会出发RowUpdating事件,单击“取消”按钮会触发RowCancelingEdit事件。我们需要写入自己在RowUpdating事件里写自己的更新代码。
填加如下的代码到RowEditing事件当中:
(object sender, GridViewEditEventArgs e)
{
GridView1.EditIndex = e.NewEditIndex;
BindGrid();
}
RowEditing事件接收一个GridViewEditEventArgs类型的变量。类GridViewEditEventArgs有一个属性叫做NewEditIndex来告诉我们用户单击的那一行的行号。然后根据这个值我们设置到GridView的EditIndex的值。这会使GridView进入到编辑模式,如下图:
注意EmployeeID这一列是不能被编辑的因为这个列已经被标志成ReadOnly.
然后我们填加如下代码到RowCancelingEdit事件当中。
(object sender, GridViewCancelEditEventArgs e)
{
GridView1.EditIndex = -1;
BindGrid();
}
这里我们把EditIndex的值设置成-1告诉系统我们现在要取消编辑操作。
最后,我们来看看RowUpdating事件的代码:
(object sender, GridViewUpdateEventArgs e)
{
int empid;
string fname, lname;
empid = int.Parse(GridView1.Rows[e.RowIndex].
Cells[0].Text);
fname = ((TextBox)GridView1.Rows[e.RowIndex].
Cells[1].Controls[0]).Text;
lname = ((TextBox)GridView1.Rows[e.RowIndex].
Cells[2].Controls[0]).Text;
SqlConnection cnn = new SqlConnection(@"data source=
.\sqlexpress;initial catalog=northwind;integrated
security=true");
cnn.Open();
SqlCommand cmd = new SqlCommand("update employees set
firstname=@fname,lastname=@lname where employeeid=@empid",
cnn);
cmd.Parameters.Add(new SqlParameter("@fname",fname));
cmd.Parameters.Add(new SqlParameter("@lname", lname));
cmd.Parameters.Add(new SqlParameter("@empid", empid));
cmd.ExecuteNonQuery();
cnn.Close();
GridView1.EditIndex = -1;
BindGrid();
}
这里我们先得到在TextBox里我们输入的值。RowUpdating方法接收一个GridViewUpdateEventArgs类型的变量,GridViewUpdateEventArgs类有一个叫做RowIndex的属性告诉系统哪一行正在被更新。系统用GridView的Rows集合来获得新输入的值。注意系统是怎么利用Cells和Controls集合的。Cells集合包含了所有正在被编辑的这些列的对象。Controls集合存储所把所有的空间都存储成Control类型。因此系统需要把这些控件变成TextBox类型的对象。然后我们再用connection,command等数据库对象执行一个UPDATE操作。当更新操作完成后,系统会把GridView的EditIndex属性设置成-1来完成更新操作。
BindGrid()方法:
前面我们提到过的这个方法,其代码如下:
{
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter
("select * from employees", @"data source=
.\sqlexpress;initial catalog=northwind;
integrated security=true");
da.Fill(ds,"employees");
DataView dv = ds.Tables[0].DefaultView;
if (ViewState["sortexpression"] != null)
{
dv.Sort = ViewState["sortexpression"].ToString()
+ " " + ViewState["sortdirection"].ToString();
}
GridView1.DataSource=dv;
GridView1.DataBind();
}
通过这个方法,我们把Employees表里的数据填充到一个DataSet里。然后基于employees表创建一个DataView,再根据Sort属性来对其排序。每一列需要排序的属性都从ViewState变量里获得sortexpression属性。而当排序正在进行的时候也同样是用到了这个变量,还记得我们在Sorting事件里设置的那两个属性吗?就是它们。最后,我们把GridView的DataSource属性在DataBind()方法里设置成这个DataView。
总结
GridView是可以不用DataSource控件直接绑定到DataView或DataTable上的。我们同样可以实现分页,排序和编辑的功能。只不过,我们需要自己写相应的代码而已。
译者后续:
整体来说这个文章的难度不是很大,不过却涉及到了最基本的ASP.NET的编程模型,目的是希望帮助更多的人来了解ASP.NET.让大家更熟悉其结构和运行模式,也可以让更多的人顺着此思路来更深一层次的掌握ASP.NET.
有意思的是有些地方翻译起来很憋嘴,但是却知道作者在说什么意思,所以干脆就直接拿自己的语言来表达作者的意思了。
另外最近由于项目的需要,正在研究从现有查询系统的网站上抽取数据的方法,网上虽然能搜索到结果但是说的都很粗略,也正好也赶上项目有需要所以有机会研究这方面东西。为什么要提取,我们也知道现在很多治安管理系统都是很老的,基本上都是1999年那时候做出来的,并且每个系统都是不同公司做的,所以打算根据这些查询系统自己写一个提取查询结果信息页的方法,并且发布成Webservice来供其它类型的软件或设备访问。