让你的GridView、DataList 的数据行同时具有单击或双击选中的功能

Note: 

        英文原文链接:http://www.codeproject.com/KB/webforms/DoubleClickGridviewRow.aspx

        网上有很多方法不仅可以实现在GridView的一行的任意位置单击实现选中功能,而且也可以实现双击选中的功能。但我还没有遇到过能同时具有单击和双击功能,并且可以很好的解决event validation errors 。

    这里,我将给出一种可以在ASP.NET2.0下同时实现行的单/双击选中行的方法,其适用范围有 GridViewDataList , ListBox等控件。

  

 背景:

  当开发一个ASP.NET的应用程序去代替传统的Windows应用程序,经常被要去使其用户体验接近于传统模式。传统的应用程序允许用户选中工具栏中的行,并执行其事件响应。通过点击一行,可以打开另一个Form,并看到其细节。这种功能可以很容易的通过在GridView中设置两个隐藏的ButtonField去实现,当然我要做的比这样更好。


  可单/双击的GridView

  创建一个Web应用程序,其默认页面为Default.aspx. 现在, 事 EnableEventValidation="false" . 我们以后再移除它.添加一个 GridView并绑定数据源. 在GridVIew上点击-编辑列-添加两个 asp:ButtonField . 分别为其命名为 SingleClick和DoubleClick

   

  1. <Columns>  
  2.     <asp:ButtonField Text="SingleClick" CommandName="SingleClick" />  
  3.     <asp:ButtonField Text="DoubleClick" CommandName="DoubleClick" />  
  4. </Columns>  

    添加GridView的 RowCommand事件,并用Switch语句去捕获其选中事件。下面的示例将在页面显示你所选中过GridView行的索引列表。 

  1. protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)  
  2. {  
  3.     GridView _gridView = (GridView)sender;  
  4.   
  5.     // Get the selected index and the command name  
  6.   
  7.     int _selectedIndex = int.Parse(e.CommandArgument.ToString());  
  8.     string _commandName = e.CommandName;  
  9.   
  10.     switch (_commandName)  
  11.     {  
  12.         case ("SingleClick"):  
  13.             _gridView.SelectedIndex = _selectedIndex;  
  14.             this.Message.Text += "Single clicked GridView row at index "  
  15.             + _selectedIndex.ToString() + "<br />";  
  16.         break;  
  17.         case ("DoubleClick"):  
  18.             this.Message.Text += "Double clicked GridView row at index "  
  19.             + _selectedIndex.ToString() + "<br />";  
  20.         break;  
  21.     }  
  22. }  

      添加 RowDataBound 事件在绑定数据时修改每一行的属性。现在,我们需要为每一行添加客户端脚本(即添加onclick),该脚本作用于SingleClick按钮。

  1. if (e.Row.RowType == DataControlRowType.DataRow)  
  2. {  
  3.     // Get the LinkButton control in the first cell  
  4.   
  5.     LinkButton _singleClickButton = (LinkButton)e.Row.Cells[0].Controls[0];  
  6.     // Get the javascript which is assigned to this LinkButton  
  7.   
  8.     string _jsSingle =   
  9.     ClientScript.GetPostBackClientHyperlink(_singleClickButton, "");  
  10.     // Add this javascript to the onclick Attribute of the row  
  11.   
  12.     e.Row.Attributes["onclick"] = _jsSingle;  
  13. }  

   同理,我们可以对DoubleClick按钮做同样操作,但两者不会同时起作用。

 

  1. if (e.Row.RowType == DataControlRowType.DataRow)  
  2. {  
  3.     // Get the LinkButton control in the second cell  
  4.   
  5.     LinkButton _doubleClickButton = (LinkButton)e.Row.Cells[1].Controls[0];  
  6.     // Get the javascript which is assigned to this LinkButton  
  7.   
  8.     string _jsDouble =   
  9.     ClientScript.GetPostBackClientHyperlink(_doubleClickButton, "");  
  10.     // Add this JavaScript to the ondblclick Attribute of the row  
  11.   
  12.     e.Row.Attributes["ondblclick"] = _jsDouble;  
  13. }  
   虽然我们实现了响应单击和双击事件,但实际我们只能得到单击响应的功能。因为如果用户进行了双击,双击中的第一次就被作为单击响应。JS中的setTimeout方法可以对第一次响应设置超时,这样用户就可以完成一次双击。 

  1. onclick="javascript:__doPostBack('GridView1$ctl02$ctl00','')"  

      将超时设置为300毫秒

  1. onclick="javascript:setTimeout  
  2.         ("__doPostBack('GridView1$ctl02$ctl00','')", 300)"  

      完整的DataRowBound的代码如下:

  1. protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)  
  2. {  
  3.     if (e.Row.RowType == DataControlRowType.DataRow)  
  4.     {  
  5.         // Get the LinkButton control in the first cell  
  6.   
  7.         LinkButton _singleClickButton = (LinkButton)e.Row.Cells[0].Controls[0];  
  8.         // Get the javascript which is assigned to this LinkButton  
  9.   
  10.         string _jsSingle =   
  11.         ClientScript.GetPostBackClientHyperlink(_singleClickButton, "");  
  12.         // To prevent the first click from posting back immediately  
  13.   
  14.         // (therefore giving the user a chance to double click)   
  15.   
  16.     // pause the postbackfor 300 milliseconds by   
  17.   
  18.         // wrapping the postback command in a setTimeout  
  19.   
  20.         _jsSingle = _jsSingle.Insert(11, "setTimeout(\"");  
  21.         _jsSingle += "\", 300)";  
  22.         // Add this javascript to the onclick Attribute of the row  
  23.   
  24.         e.Row.Attributes["onclick"] = _jsSingle;  
  25.   
  26.         // Get the LinkButton control in the second cell  
  27.   
  28.         LinkButton _doubleClickButton = (LinkButton)e.Row.Cells[1].Controls[0];  
  29.         // Get the javascript which is assigned to this LinkButton  
  30.   
  31.         string _jsDouble =   
  32.         ClientScript.GetPostBackClientHyperlink(_doubleClickButton, "");  
  33.         // Add this javascript to the ondblclick Attribute of the row  
  34.   
  35.         e.Row.Attributes["ondblclick"] = _jsDouble;  
  36.     }  
  37. }  

    此时,这两个按钮应该设置为隐藏

    

  1. <Columns>  
  2.     <asp:ButtonField Text="SingleClick" CommandName="SingleClick"   
  3.                             Visible="false" />  
  4.     <asp:ButtonField Text="DoubleClick" CommandName="DoubleClick"   
  5.                             Visible="false" />  
  6. </Columns>  
    

    现在,RowCommand可以同时捕捉到GridView一行的单双击事件了。

    
    注册用以验证的postback 和callback数据


 一切都运行的很好,请别忘记一开始我们设置了 EnableEventValidation="false"  ,这不是安全的选项,我们要移除它。这在单击时将导致出现"Invalid postback or callback argument" 错误。这个错误告诉我们去使用theClientScriptManager.RegisterForEventValidation 去注册postback或callback数据。
  ClientScriptManager.RegisterForEventValidation可以被重载的Render方法调用。这里的关键是注册GridView一行的两个按钮个unique Id。每一行的UniqueID被转换为GridView.UniqueID,第一个按钮的UniqueID仅需要在GridView.UniqueId的后面就附加上”$ctl00“,第二个按钮则附加上 "$ctl01".

 

    
  1. protected override void Render(HtmlTextWriter writer)  
  2. {  
  3.     foreach (GridViewRow r in GridView1.Rows)  
  4.     {  
  5.         if (r.RowType == DataControlRowType.DataRow)  
  6.         {  
  7.             Page.ClientScript.RegisterForEventValidation  
  8.                     (r.UniqueID + "$ctl00");  
  9.             Page.ClientScript.RegisterForEventValidation  
  10.                     (r.UniqueID + "$ctl01");  
  11.         }  
  12.     }  
  13.   
  14.     base.Render(writer);  
  15. }  


现在将不会出现任何“invalid postback or callback argument”错误了。


    结论

      通过JS与ASP.NET的紧密结合,我们可以扩展GridView和DataList的功能。为了你的程序的安全,如果可以的话,你不应该将EnableEventValidation="false" 。一旦你理解了EventValidation是如何工作的,你可以使用ClientScript.RegisterForEventValidation却包你的代码执行的更安全
url:
http://greatverve.cnblogs.com/archive/2011/12/19/gridview-datalist-click-doubleclick.html

posted @ 2011-12-19 08:49  大气象  阅读(3762)  评论(11编辑  收藏  举报
http://www.tianqiweiqi.com