Leepy's Blogs

专注于ajax技术,windows mobile技术,GIS技术 English(beta)
posts - 84, comments - 120, trackbacks - 5, articles - 66
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

用GridView编辑更新独立的单元格

Posted on 2007-12-16 11:32 Leepy 阅读(3143) 评论(17)  编辑 收藏

翻译出处:http://www.codeproject.com/KB/webforms/EditGridviewCells.aspx

源代码下载

介绍

asp.net 中,GridView允许你通过EditIndex属性来修改数据的一行,同样也必须进行整行更新。

你可能不想对整行进行更新,并且常规更新是利用EditItemTemplate,在它内部放上编辑状态所要显示的控件;而事实上,你可能只对其中一个单元格感兴趣,比如用上DropDownList来进行单元格筛选,而常规必须整行成编辑状态,那怎样才能直接只让一个独立的单元格成编辑状态呢?那就是本篇文章所要做的事情。

编辑独立的单元格

Screenshot - EditGridviewCells1.jpg
本篇提供的源代码中,
GridView的第一列是CommandNameSingleClickasp:ButtonField的控件,并且它的Visiblefalse.

这控件是为了点击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>

想法是这样的,刚开始GridView处于显示状态(也就是“非编辑状态”),当某一个单元格被点击的时候,它把Label控件置不可见而编辑控件TextBox或者DropdownList置肯见,而EditItemTemplate不需要用到。

GridViewRowDataBound的事件内对每一行中的每个单元格进行遍历,让其拥有点击触发事件的能力。

给每个单元的列索引定义上一些属性参数,如onclickstyle等等。
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
    
if (e.Row.RowType == DataControlRowType.DataRow)
    
{
        
// 得到第一个单元格的LinkButton控件
        LinkButton _singleClickButton = (LinkButton)e.Row.Cells[0].Controls[0];
        
// 得到客户端javascript能够引起LinkButton回发事件的脚本
        string _jsSingle = ClientScript.GetPostBackClientHyperlink(
            _singleClickButton, 
"");

        
// 添加事件到每个可编辑的单元格
        for (int columnIndex = _firstEditCellIndex; columnIndex < 
            e.Row.Cells.Count; columnIndex
++)
        
{
            
// 插入列索引参数
            string js = _jsSingle.Insert(_jsSingle.Length - 2
                columnIndex.ToString());
            
// 给单元格添加javscript的onclick属性
            e.Row.Cells[columnIndex].Attributes["onclick"= js;
            
// 给单元格添加鼠标样式
            e.Row.Cells[columnIndex].Attributes["style"+= 
                
"cursor:pointer;cursor:hand;";
        }

    }

}


GridViewRowCommand事件,命令参数和事件参数被重新检索,它带给我们选择某一单元格所在的行索引和列索引。
int _rowIndex = int.Parse(e.CommandArgument.ToString());
int _columnIndex = int.Parse(Request.Form["__EVENTARGUMENT"]);

当所选单元格的行索引和列索引已知的情况下,单元格能够很轻松地对编辑状态进行控件的可见转换。

被选中的单元格也必须移除点击的事件。

//得到选中单元格的显示控件使它不可见
Control _displayControl = 
    _gridView.Rows[_rowIndex].Cells[_columnIndex].Controls[
1];
_displayControl.Visible 
= false;
// 得到选中单元格的编辑控件是它可见
Control _editControl = 
    _gridView.Rows[_rowIndex].Cells[_columnIndex].Controls[
3];
_editControl.Visible 
= true;
// 移除选中单元格的点击属性
   _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()");
}


在这个例子中,GridViewRowUpdating先检查每个单元格,看是否处于编辑模式下。如果处于编辑模式的单元格被找到,那么数据更新将被执行。

在第一个例子中,一些样本数据绑定到一个DataTable中存储在Session
// 遍历GridView的列索引查找处于编辑模式下的单元格
for (int i = 1; i < _gridView.Columns.Count; i++)
{
    
// Get the editing control for the cell
    Control _editControl = _gridView.Rows[e.RowIndex].Cells[i].Controls[3];
    
if (_editControl.Visible)
    
{
       
// 更新数据
    }

}


为了确保RowUpdatingGridView在未选中行状态下也能够被调用,例如我在编辑模式下编辑文本框点击了“Enter”键,页面整页回发,这样确保任何数据的改变被保存。
if (this.GridView1.SelectedIndex > -1)
{
    
this.GridView1.UpdateRow(this.GridView1.SelectedIndex, false);
}


注册回发或回调数据以进行验证

创建在RowDataBound的自定义事件必须在页面中被注册。

ClientScriptManager.RegisterForEventValuedation通过重载Render方法来调用。

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);
}

Feedback

#1楼    回复  引用    

2007-12-16 13:05 by good man [未注册用户]
very good

#2楼    回复  引用    

2007-12-16 14:47 by fjyou [未注册用户]
是vs2008的?

#3楼 [楼主]   回复  引用  查看    

2007-12-16 15:35 by Leepy      
@fjyou
例子是2005的!

#4楼    回复  引用    

2007-12-16 18:36 by fjyou [未注册用户]
打开编译出现web.config错误

#5楼 [楼主]   回复  引用  查看    

2007-12-16 19:25 by Leepy      
@fjyou
它的默认web.config为.net 3.5版本的,你要使用Web.Net2.0.Config,将其改为web.config

#6楼    回复  引用  查看    

2007-12-17 09:47 by jeff377      
它的範例做的不錯,不過比較好的作法是直接擴充 ObjectDataSource,讓 ObjectDataSource 可以存取 Session 或 Cache 的 DataTable,這樣就不用在 GridView 寫一堆程式碼。

#7楼    回复  引用    

2007-12-17 10:25 by bluesky------yiyuan [未注册用户]
挺不错的文章,顶 呵呵

#8楼    回复  引用  查看    

2007-12-17 13:37 by bidaas      
史上最强复杂方法

#9楼    回复  引用    

2008-02-18 22:46 by 454545 [未注册用户]
找不到_firstEditCellIndex和_gridView的定义
请高手指教
先谢了!!!

#10楼 [楼主]   回复  引用  查看    

2008-02-19 09:15 by Leepy      
@454545
文件中有定义

#11楼    回复  引用    

2008-02-19 12:26 by xk [未注册用户]
int _rowIndex = int.Parse(e.CommandArgument.ToString());
句中出现CS0117: “System.Web.UI.WebControls.GridViewRowEventArgs”并不包含“CommandArgument”的定义 错误

还有_firstEditCellIndex和_gridView的代表含义?如何定义?

#12楼 [楼主]   回复  引用  查看    

2008-02-19 15:13 by Leepy      
@xk
Button点击是在GridView1_RowCommand触发的,对应的是GridViewCommandEventArgs;

_firstEditCellIndex是指在从第几列开始可以进行为编辑列;_gridView是为了捕获事件所在的源;

#13楼    回复  引用    

2008-02-19 16:10 by xk [未注册用户]
可以传问代码贴出来学习吗?

#14楼    回复  引用    

2008-02-19 16:11 by xk [未注册用户]
可以全部代码贴出来看看吗?

#15楼 [楼主]   回复  引用  查看    

2008-02-19 19:44 by Leepy      
@xk
代码在文章顶上有啊!

#16楼    回复  引用  查看    

2008-04-16 10:58 by ke7in      
--引用--------------------------------------------------
454545: 找不到_firstEditCellIndex和_gridView的定义
请高手指教
先谢了!!!
--------------------------------------------------------
private const int _firstEditCellIndex = 2;
GridView _gridView = (GridView)sender;

#17楼    回复  引用    

2008-06-30 15:15 by smilesky [未注册用户]
编辑之后怎么保存更新后的数据呢?GridView的RowUpdating事件触发不了!

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-12-16 11:36 编辑过


相关链接: