原文地址: http://www.codeproject.com/KB/webforms/EditGridviewCells.aspx
[原文源码下载]
[译者改后源码下载]

作者:Declan Bright
翻译:webabcd

介绍
ASP.NET的GridView控件允许你通过设置它的EditIndex属性来编辑数据行,此时整个数据行都处于编辑模式。 如果你在EditItemTemplate的一些列中使用了DropDownList控件,那么你也许不希望整个数据行都处于编辑模式。 因为,如果每一个DropDownList控件都有很多选项的话,那么一次加载所有DropDownList控件的所有选项就会导致页面执行缓慢。

另外,如果你的数据行的编辑模式需要占用更多的空间的话,那么针对每一个独立的单元格进行编辑要优于针对整个数据行进行编辑。 这里,我将示范如何实现这样的功能,又如何去处理事件验证(event validation)。

背景
本文基于我之前写的一篇文章: GridView和DataList响应单击数据行和双击数据行事件 。如果你不知道如何让GridView响应单击数据行事件,那么你可以在阅读本文之前先看看这篇文章。

编辑某一个独立的GridView单元格。

我所演示的这个GridView有一个不可见的asp:ButtonField控件,它处于GridView的第一列,名为“SingleClick”。 它用于给GridView的数据行增加单击事件。

<Columns>                
    <asp:ButtonField Text="SingleClick" CommandName="SingleClick" Visible="False" />
</Columns>

其它每一列的ItemTemplate中有一个可见的Label控件和一个不可见的TextBox或DropDownList控件。 为了方便,我们称Label为显示控件,TextBox或DropDownList为编辑控件。

    <asp:TemplateField HeaderText="Task">
        <ItemTemplate>
            <asp:Label ID="DescriptionLabel" runat="server" Text='<%# Eval("Description") %>'></asp:Label>
            <asp:TextBox ID="Description" runat="server" Text='<%# Eval("Description") %>' Width="175px" visible="false"></asp:TextBox>
        </ItemTemplate>
    </asp:TemplateField>

这里的办法就是用显示控件来显示数据,当单元格所包含的显示控件被单击的时候,则把显示控件的Visible属性设置为false并且把编辑控件的Visible属性设置为true。 这里不用使用EditItemTemplat。

在RowDataBound事件内循环为每一数据行的每一单元格增加单击事件。 使用单元格在数据行中的索引作为事件参数,这样在单元格触发了单击事件后我们就可以知道到底是哪个单元格被单击了。

    protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            // 从第一个单元格内获得LinkButton控件
            LinkButton _singleClickButton = (LinkButton)e.Row.Cells[0].Controls[0];
            // 返回一个字符串,表示对包含目标控件的 ID 和事件参数的回发函数的 JavaScript 调用
            string _jsSingle = ClientScript.GetPostBackClientHyperlink(_singleClickButton, "");

            // 给每一个可编辑的单元格增加事件
            for (int columnIndex = _firstEditCellIndex; columnIndex < e.Row.Cells.Count; columnIndex++)
            {
                // 增加列索引作为事件参数
                string js = _jsSingle.Insert(_jsSingle.Length - 2, columnIndex.ToString());
                // 给单元格增加onclick事件
                e.Row.Cells[columnIndex].Attributes["onclick"] = js;
                // 给单元格增加鼠标经过时指针样式
                e.Row.Cells[columnIndex].Attributes["style"] += "cursor:pointer;cursor:hand;"; 
            }     
        }
    }

在RowCommand事件内读出命令参数和事件参数。 这会告诉我们被选中的行和列的索引。

    int _rowIndex = int.Parse(e.CommandArgument.ToString());      
    int _columnIndex = int.Parse(Request.Form["__EVENTARGUMENT"]);

因为知道了被选中的行和列的索引,所以可以通过把显示控件的Visible设置为false,编辑控件的Visible设置为true来把某个独立的单元格设置为编辑模式。 然后通过清除单元格的属性来删除被选中单元格的单击事件。

    // 获得被选中单元格的显示控件并设置其不可见
    Control _displayControl = _gridView.Rows[_rowIndex].Cells[_columnIndex].Controls[1]; 
    _displayControl.Visible = false;
    // 获得被选中单元格的编辑控件并设置其可见
    Control _editControl = _gridView.Rows[_rowIndex].Cells[_columnIndex].Controls[3];
    _editControl.Visible = true;
    // 清除被选中单元格属性以删除click事件
    _gridView.Rows[_rowIndex].Cells[_columnIndex].Attributes.Clear();

下面有一些代码用于回发服务器后设置焦点到编辑控件,如果编辑控件是DropDownList的话,那么它的SelectedValue要设置为显示控件的值,如果编辑控件是TextBox的话,那么为了做好编辑的准备就要使它的文本被选中。

    // 设置焦点到被选中的编辑控件
    ClientScript.RegisterStartupScript(GetType(), "SetFocus", 
        "<script>document.getElementById('" + _editControl.ClientID + "').focus();</script>");
    // 如果编辑控件是DropDownList的话
    // SelectedValue设置为显示控件的值
    if (_editControl is DropDownList && _displayControl is Label)
    {
        ((DropDownList)_editControl).SelectedValue = ((Label)_displayControl).Text;
    }                 
    // 如果编辑控件是TextBox的话则选中文本框内文本
    if (_editControl is TextBox)
    {
       ((TextBox)_editControl).Attributes.Add("onfocus", "this.select()");
    }

在这个Demo中,我把事件被触发的历史记录也写到了页里。

如果GridView处于编辑模式的话,那么要在RowUpdating事件里去查找被选中行的每一个单元格。 如果发现单元格处于编辑模式的话,那么就调用“更新”代码。 在这个Demo中,数据保存在DataTable里,而这个DataTable则储存在session中。

    // 循环每一列以找到处于编辑模式下的单元格
    for (int i = 1; i < _gridView.Columns.Count; i++)
    {
        // 获得单元格的编辑控件
        Control _editControl = _gridView.Rows[e.RowIndex].Cells[i].Controls[3];
        if (_editControl.Visible)
        {
           . update the data
        }
    }

为了确保RowUpdating事件在编辑单元格后被激发,要在Page_Load中来触发这个事件。 编辑了TextBox后,通过按回车键或者单击另一单元格来使页面做回发处理,下面的这段代码就是用于确保任何数据的改变都会被更新。

    if (this.GridView1.SelectedIndex > -1)
    {
        this.GridView1.UpdateRow(this.GridView1.SelectedIndex, false);
    }   

为了验证而注册回发和回调数据
在RowDataBound中创建的自定义事件必须要在页中注册。 通过重写Render方法来调用ClientScriptManager.RegisterForEventValidation。 通过GridViewRow.UniqueID返回行的唯一ID,按纽的唯一ID通过在行的唯一ID后附加“$ct100”而生成。

    protected override void Render(HtmlTextWriter writer)
    {
        foreach (GridViewRow r in GridView1.Rows)
        {
            if (r.RowType == DataControlRowType.DataRow)
            {
                for (int columnIndex = _firstEditCellIndex; columnIndex < r.Cells.Count; columnIndex++)
                {
                    Page.ClientScript.RegisterForEventValidation(r.UniqueID + "$ctl00", columnIndex.ToString());
                }
            }
        }
      
        base.Render(writer);
    }

这将防止任何“回发或回调参数无效”的错误。

这个Demo中的其它示例
使用SQL数据源控件编辑某一独立的GridView单元格
用SqlDataSouce控件实现这个技术需要对GridView的RowUpdating事件做一些修改。 当更新GridView的行的时候,SqlDataSource控件一般要把值(values)从EditItemTemplate转移到NewValues集合里。 因为我们没有使用EditItemTemplate,所以这种情况下值(values)不会自动地转移到NewValues集合里。

    e.NewValues.Add(key, value);

我在App_Data文件夹下使用了一个简单的SQL Server Express数据库。 (要使用你自己的数据库的话,你可以修改web.config里的连接字符串)

使用对象数据源控件编辑某一独立的GridView单元格
本示例使用了App_Code文件夹内的两个类:
    ·Task.cs – 任务对象
    ·TaskDataAccess.cs – 管理任务对象

Aspx页的后置代码与SQL Data Source示例是一样的。 ObjectDataSource通过TaskDataAccess.cs类里的GetTasks和UpdateTask方法来管理数据。

有着电子数据表样式的GridView
这里有一个与电子数据表的样式很像的GridView。 (虽然它看起来像一个电子数据表,但是并不是真的有像电子数据表一样的功能,它仍然是一个GridView。)

这里虽然有一些单击后改变单元格样式的附加代码,但是主要的代码还是与上面所述是相同的。

用SQL数据源控件实现有着电子数据表样式的GridView
本示例与上面的基本相同,但是它修改了GridView的RowUpdating事件以使其允许用SqlDataSource控件来工作。

参考
    · GridView和DataList响应单击数据行和双击数据行事件
    · ASP.NET 2.0数据教程

结论
如果你想在GridView中一次只针对一个单元格进行编辑,那么这个方法将会对你有所帮助。

译者注:事件验证(EventValidation)。出于安全目的,此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用ClientScriptManager.RegisterForEventValidation方法来注册回发或回调数据以进行验证。

在GridView中针对鼠标单击的某一独立单元格进行编辑相关推荐

  1. 在Excel中批量下载网络图片,存放到右方单元格或插入到批注,#excel插件

    Excel工作表中有图1所示的若干图片网址,否则批量转换成图2所示的结果? 也就是根据A列的网页图片地址批量下载图片,存放到B列中. 图1 以jpg结尾的图片网址 图2 插入图片到右方单元格 或者能否 ...

  2. ElementUI table组件,表格组件,单击单元格可编辑逻辑

    ElementUI table组件,表格组件,单击单元格可编辑逻辑 1.表格部分 <el-table:data="seatDataFilter"@cell-click=&qu ...

  3. excel中统计每一行中指定字体颜色和填充颜色的单元格求和(不使用VBA)

    今天早上同事问了一个看似简单,但是实现起来却一头雾水的问题.那就是对着满屏幕"五颜六色"的数字,要求出每一行中指定颜色的单元格的数值之和.(如下图,因涉及数据敏感性,简易表示一下) ...

  4. abap al设置单元格可编辑 oo_OO ALV常用功能完整简例(热键单击,双击,帮助,编辑,自定义工具条等)...

    一.所用类: cl_gui_alv_grid cl_gui_docking_container 二.效果图: 执行: 单击 双击 F4帮助 航班单元格上F4或点击 后面的小按钮 (本功能在设置字段样式 ...

  5. Excel 2016从一列中筛选全是字母或者中文的单元格

    Excel 2016从一列中筛选全是字母或者中文的单元格 1. 需求 2. 使用公式 2.1IF()函数 2.2 LEN()和LENB()函数 3. 解决需求 4. 知识扩展 1. 需求 如下图所示, ...

  6. GridView中的CheckBox单击事件(oncheckedchanged)

    在GridView中加入 CheckBox控件,想通过单击选中出现如下图所示效果: 具体做法是: 前台GV部份省掉.只加关键的CheckBox部份. <asp:CheckBox ID=" ...

  7. word单元格斜网格_如何在Word中的所有表上显示和隐藏单元格网格线

    word单元格斜网格 By default, when you create a new table, all the cells have black borders that print with ...

  8. qt中json构造一个数组_告别撸单元格!我来分享Excel中如何利用一条公式得到一个数组...

    来分享一个Excel中小众的大招."小众的大招"--这么说不矛盾.在Excel表格中利用一条公式来得到一个数组是一个高深且晦涩的话题.多数人不懂什么是数组,所以遇到此类文章或应用实 ...

  9. 单元格中指定内容标红_按照指定单元格内容进行拆分,想怎么拆就怎么拆

    前景提要 好了今天我们来继续玩一下工作表的拆分,之前我们已经尝试了用指定列,指定行的方式来进行工作表的拆分,不知道有没有点燃小伙伴们的拆分热潮呢?之前我在写按照工作表的指定行数进行拆分的时候,就想到一 ...

最新文章

  1. HDU3007(最小圆覆盖问题)
  2. 「 深入浅出 」集合List
  3. 近世代数--整环--高斯整环
  4. Android App列表之游标ListView(索引ListView)
  5. 请问在allegro中如何在铜箔上单独放置过孔?
  6. B1007 素数对猜想
  7. java二叉查找算法_Java手写二叉搜索树算法
  8. EFCore 5 新特性 Savepoints
  9. binlog日志_【删库跑路】使用Binlog日志恢复误删的MySQL数据
  10. 浅谈开发中的MVVM模式及与MVP和MVC的区别
  11. docker_4 数据卷技术
  12. .html(),.text()和.val()的差异总结:
  13. vue+ckplayer+rtmp
  14. 红米note3全网通_标注:2015112_官方线刷包_救砖包_解账户锁
  15. Problem L: 求一元二次方程的根
  16. Stream报错:stream has already been operated upon or closed
  17. [WDS] Disconnected!问题解决
  18. 卷积神经网络在物联网场景中的应用初探
  19. ADB LOGCAT CMD
  20. 《阿里云的这群疯子》

热门文章

  1. 【Android Gradle 插件】Gradle 映射文件 ( settings.gradle 映射为 Settings 类 | build.gradle 映射为 Project 类 )
  2. 【错误记录】IntelliJ IDEA 中 Java 代码中的中文注释报错 ( Menu / File / Settings / Editor / File Encodings 中修改工程编码 )
  3. 【Groovy】Groovy 方法调用 ( 字符串切割 | 使用 Java 语法切割字符串 | 使用 Groovy 语法切割字符串直接为变量赋值 | 数组赋值给变量 变量个数小于等于数组长度 )
  4. 【EventBus】事件通信框架 ( 总结 | 手写事件通信框架完整代码示例 | 测试上述框架 )
  5. 【错误记录】Android Studio 编译报错 ( Invalid Gradle JDK configuration found )
  6. 【Flutter】Flutter 拍照示例 ( Android 应用兼容 Android X | Gradle 版本号 | Gradle 插件版本号 | Android X 支持 | SDK 版本 )
  7. 【Netty】Netty 异步任务模型 及 Future-Listener 机制
  8. 虚拟机VM三种网络连接方式说明
  9. 008 python接口 unittest
  10. 使用urllib2简单爬取并保存内涵吧内涵段子指定分页的的描述信息