Asp.net的GridView只能进行单行编辑(设置EditIndex),相比之下,这个控件则可以进行多行同时编辑。同时还能进行多行插入。再配合DataSource控件,真的比较好用。
1:配合DataSource控件使用
2:多行编辑
3:多行插入
4:处理修改/插入事件
5:分页
6:模板的使用
7:小扩展
这是一个运行效果图。

这是下载地址:http://www.codeplex.com/ASPNetRealWorldContr/Release/ProjectReleases.aspx?ReleaseId=1674
配合使用Datasource控件。
再提供的例子里面,数据源使用的是SqlDataSource控件。配置好sql语句就可以了。因为我的用例里面多数都是使用ORM的,所以我用了另外一种DataSource控件。这个数据源控件的好处是对分页支持非常好,可以直接内置在对象的sql语句里面,真的可以做到数据库分页和UI分页结合。
因为设计的关系,如果不使用DataSource控件,将很难使用到多行插入的功能。
private void InsertRow(int rowIndex, bool causesValidation)
{
GridViewRow row = null;
if ((!causesValidation || (this.Page == null)) || this.Page.IsValid)
{
DataSourceView dsv = null;
bool useDataSource = base.IsBoundUsingDataSourceID;
if (useDataSource)
{
dsv = this.GetData();
if (dsv == null)
{
throw new HttpException("DataSource Returned Null View");
}
}
….
多行编辑
其实这个控件把所有行都变成了编辑状态。这种用例可能在某些场合非常有用。
BulkEditGridView直接提供一个DirtyRows的属性,把修改行触发事件。
protected void BulkEditGridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
//user logic here.
string s = e.NewValues["Manhour"].ToString().Trim();
if (s == "0" || s == "")
e.Cancel = true; //can do the cancel here.
else
{
e.NewValues["Amount"] = 100;//test reset some value
}
}
这样,就可以得到数据了。
如果不使用Datasource控件,需要做些特别的处理
if (EditableGrid.DirtyRows[EditableGrid.DirtyRows.Count-1].RowIndex == e.RowIndex)
BindData();
这样做的原因是:修改完成之后要重新绑定数据,而这个事件会被重复触发,所以一定要判断出来是不是最后一次触发这个事件,要不然直接绑定新数据的话会把其他行覆盖掉。
多行插入
这个功能看起来比较有意思:一个GridView下边会有多个新行以供用户书写新的数据。用户可以设置现实多少个新行。
不过这个功能感觉多有不方便的地方。比方说:
1:很难得到新行的GridViewRow属性。解决方法是自己扩展GridViewInsertEventArgs类。
这种调用失败:(EditableGrid.Rows[args.RowIndex].Cells[0].Controls[0] as TextBox).Text
2:无法得到新行创建的事件。在OnRowCreted事件里面只有普通行的,找不到新行的创建事件。他的实现里面是这样的:this.InnerTable.Rows.AddAt(index, row);
在提供的新的事件里面,我们可以处理插入:
protected void BulkEditGridView1_RowInserting(object sender, RealWorld.Grids.GridViewInsertEventArgs args)
{
string s = args.NewValues["Manhour"].ToString().Trim();
if (s == "0"||s=="")
args.Cancel = true;
else
{
//args.Row is my New GridViewInsertEventArgs property.
DropDownList list = args.Row.FindControl("DropDownList1") as DropDownList;
string x = list.SelectedValue;
}
}
注意:上边的args.Row是我自己扩展出来的。
这个事件也会循环触发。
分页
我使用的是一个DataSource控件,所以处理分页正好使用。因为BulkEditGridView控件本身就继承自GridView,所以分页,排序等功能继续使用没有问题。
模板列
GridView的模板列可以继续使用。但是在InsertRow的时候需要自己做一些扩展(原因就是上边说的无法得到当前事件Row的参数的问题)。
1:无法得到当前事件Row的参数的问题。这个可以通过扩展GridViewInsertEventArgs类来实现,上边已经说了。
2:无法得到新建row的创建事件的问题。这个也需要自己做一些扩展。主要是在int index = this.InnerTable.Rows.Count - (this.ShowFooter ? 1 : 0);
this.InnerTable.Rows.AddAt(index, row);附近,自行触发一个事件。
这种情况可能出现在:设置了模板,但是无法控制InsertRow里面的某些非数据绑定控件(Dropdownlist或者其他)。
其他
DropDownField类:这是提供的一个可以绑定列表的绑定列。类似的自己可以扩展其他绑定列。
附,扩展之后的GridViewInsertEventArgs类

GridViewInsertEventArgs
1
public class GridViewInsertEventArgs : CancelEventArgs
2
{
3
private int _rowIndex;
4
private IOrderedDictionary _values;
5
private GridViewRow _row;
6
7
public GridViewInsertEventArgs(int rowIndex)
8
: base(false)
9
{
10
this._rowIndex = rowIndex;
11
}
12
/**//// <summary>
13
/// new method, to expose the current row
14
/// </summary>
15
/// <param name="row"></param>
16
public GridViewInsertEventArgs(int rowIndex,GridViewRow row)
17
: base(false)
18
{
19
this._rowIndex = rowIndex;
20
this._row = row;
21
}
22
/**//// <summary>
23
/// Gets a dictionary containing the revised values of the non-key field name/value
24
/// pairs in the row to update.
25
/// </summary>
26
public IOrderedDictionary NewValues
27
{
28
get
29
{
30
if (this._values == null)
31
{
32
this._values = new OrderedDictionary();
33
}
34
return this._values;
35
}
36
}
37
/**//// <summary>
38
/// Gets a dictionary containing the revised values of the non-key field name/value
39
/// pairs in the row to update.
40
/// </summary>
41
public GridViewRow Row
42
{
43
get
44
{
45
return this._row;
46
}
47
set
{
48
this._row = value;
49
}
50
}
51
/**//// <summary>
52
/// Gets the index of the row being updated.
53
/// </summary>
54
public int RowIndex
{ get
{ return this._rowIndex; } }
55
}