自定义列时,一般下使用GridView的CommandName属性和RowCommand()事件配合使用。而能用什么类型的列?
一般最容易的是使用ButtonField列和CommandField列,
当然,也可以用其他列,如使用模板列即TemplateField列,但会提示错误:“e.CommandArgument输入字符串的格式不正确”
但使用TemplateField列需要注意一点,就是在RowCommand事件中行索引号会丢失变为空字符串,造成无法查找到数据行。
为什么丢失行索引号呢?看了其他网友的方法总结,我个人认为GridView行索引是存储在控件列里的某个控件的CommandArgum属性中,而TemplateField列不是特定的某个控件列,其可以包含多个控件,更是一个多控件集合的整体列。行索引号只能存储在某个控件里而TemplateField列有多个控件,所以,系统在不清楚到底要把行索引号存储在哪个控件里时,就造成TemplateField列里所有的控件都没办法存储到行索引号。(这是我个人看法,如有不对,请大家多多指教。)
这个时候怎么处理呢?
可以在RowCreated事件或RowDataBound事件中用LinkButton、Button等控件的CommandArgument属性进行存储行序号值,在RowCommand事件中就可以读取到行索引号。
首先,我们先看怎么使用ButtonField列进行自定义列实现编辑、删除功能
例如:
前台页面代码:
<asp:GridView ID="dgvInfo" runat="server" AutoGenerateColumns="False" Width="100%"
DataKeyNames="ID" EmptyDataText="没有可显示的数据记录。"
onrowcommand="dgvInfo_RowCommand" AllowPaging="True"
onpageindexchanging="dgvInfo_PageIndexChanging"
onrowdatabound="dgvInfo_RowDataBound"
EmptyDataTableCssClass="datagridTable" EmptyDataTitleRowCssClass="GvTitlebg" EmptyDataContentRowCssClass="datagridContentRow">
<PagerSettings Mode="NextPreviousFirstLast" FirstPageText="首页"
LastPageText="末页" NextPageText="下一页" PreviousPageText="上一页" />
<Columns>
<asp:BoundField DataField="UserID" HeaderText="UserID"
SortExpression="UserID" Visible="false" />
<asp:BoundField DataField="UserCode" HeaderText="用户代码"
SortExpression="UserCode" />
<asp:BoundField DataField="UserName" HeaderText="用户名称"
SortExpression="UserName" />
<asp:ButtonField CommandName="Rol" Text="角色授权" />
<asp:ButtonField CommandName="Edi" Text="编辑" />
<asp:ButtonField CommandName="Del" Text="删除" />
</Columns>
</asp:GridView>
后台代码:
protected void dgvInfo_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (!string.IsNullOrEmpty(e.CommandName)) //判断命令名是否为空
{
if (e.CommandName == "Edi") //如果触发的是详细信息按钮事件
{
int index = Convert.ToInt32(e.CommandArgument); //取GridView行索引
GridView grid = (GridView)e.CommandSource; //取当前操作的GridView
int id = Convert.ToInt32(grid.DataKeys[index].Value); //取GridView主键值
Response.Redirect(@"~/UserInput.aspx?ID=" + id.ToString());
LoadData();
}
else if (e.CommandName == "Del")
{
int index = Convert.ToInt32(e.CommandArgument); //取GridView行索引
GridView grid = (GridView)e.CommandSource; //取当前操作的GridView
int id = Convert.ToInt32(grid.DataKeys[index].Value); //取GridView主键值
UserInfoService.Instance.DeleteUserInfo(id);
LoadData();
}
else if (e.CommandName == "Page")
{
LoadData();
}
else if (e.CommandName == "Rol")
{
}
}
}
以上代码中e.CommandArgument值存储行的索引号,可以正常读取,因为使用的是ButtonField列Button可以正常接收到行索引号。
如果使用TemplateField列以上后台代码就实现不了“编辑”“删除”功能。
使用TemplateField列,
<asp:ButtonField CommandName="Edi" Text="编辑" />
<asp:ButtonField CommandName="Del" Text="删除" />
代码改为:
<asp:TemplateField HeaderText="操作选项" ItemStyle-Width="100">
<ItemTemplate>
<asp:LinkButton ID="lnkbtnRoleEdit" runat="server" CommandName="Edi" >编辑</asp:LinkButton>
<asp:LinkButton ID="lnkbtnRoleDel" runat="server" CommandName="Del">删除</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
后台代码:
protected void dgvInfo_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowIndex != -1)
{
LinkButton lnkbtnRoleEdit = (LinkButton)e.Row.FindControl("lnkbtnRoleEdit");
lnkbtnRoleEdit.CommandArgument = e.Row.RowIndex.ToString();
LinkButton lnkbtnRoleDel = (LinkButton)e.Row.FindControl("lnkbtnRoleDel");
lnkbtnRoleDel.CommandArgument = e.Row.Cells[0].Text;
lnkbtnRoleDel.Attributes.Add("onclick", "return confirm('确认删除吗?');");
}
}
或者
protected void dgvInfo_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
LinkButton lnkbtnRoleEdit = (LinkButton)e.Row.FindControl("lnkbtnRoleEdit");
lnkbtnRoleEdit.CommandArgument = e.Row.RowIndex.ToString();
LinkButton lnkbtnRoleDel = (LinkButton)e.Row.FindControl("lnkbtnRoleDel");
lnkbtnRoleDel.CommandArgument = e.Row.RowIndex.ToString();
}
}
用RowDataBound和RowCreated事件哪个都行,二选一,RowCommand事件代码不变。
还有同等的一个终极方法,直接在控件的CommandArgument属性存储数据表的一个索引字段值,因为存储行索引号也是为了获取索引字段值,不如直接跳过存储行索引号。这样更快速操作数据行的编辑和删除。


