让你的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

   

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

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

protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
    GridView _gridView = (GridView)sender;

    // Get the selected index and the command name

    int _selectedIndex = int.Parse(e.CommandArgument.ToString());
    string _commandName = e.CommandName;

    switch (_commandName)
    {
        case ("SingleClick"):
            _gridView.SelectedIndex = _selectedIndex;
            this.Message.Text += "Single clicked GridView row at index "
            + _selectedIndex.ToString() + "<br />";
        break;
        case ("DoubleClick"):
            this.Message.Text += "Double clicked GridView row at index "
            + _selectedIndex.ToString() + "<br />";
        break;
    }
}

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

if (e.Row.RowType == DataControlRowType.DataRow)
{
    // Get the LinkButton control in the first cell

    LinkButton _singleClickButton = (LinkButton)e.Row.Cells[0].Controls[0];
    // Get the javascript which is assigned to this LinkButton

    string _jsSingle = 
    ClientScript.GetPostBackClientHyperlink(_singleClickButton, "");
    // Add this javascript to the onclick Attribute of the row

    e.Row.Attributes["onclick"] = _jsSingle;
}

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

 

if (e.Row.RowType == DataControlRowType.DataRow)
{
    // Get the LinkButton control in the second cell

    LinkButton _doubleClickButton = (LinkButton)e.Row.Cells[1].Controls[0];
    // Get the javascript which is assigned to this LinkButton

    string _jsDouble = 
    ClientScript.GetPostBackClientHyperlink(_doubleClickButton, "");
    // Add this JavaScript to the ondblclick Attribute of the row

    e.Row.Attributes["ondblclick"] = _jsDouble;
}
   虽然我们实现了响应单击和双击事件,但实际我们只能得到单击响应的功能。因为如果用户进行了双击,双击中的第一次就被作为单击响应。JS中的setTimeout方法可以对第一次响应设置超时,这样用户就可以完成一次双击。 

οnclick="javascript:__doPostBack('GridView1$ctl02$ctl00','')"

      将超时设置为300毫秒

οnclick="javascript:setTimeout
        ("__doPostBack('GridView1$ctl02$ctl00','')", 300)"

      完整的DataRowBound的代码如下:

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        // Get the LinkButton control in the first cell

        LinkButton _singleClickButton = (LinkButton)e.Row.Cells[0].Controls[0];
        // Get the javascript which is assigned to this LinkButton

        string _jsSingle = 
        ClientScript.GetPostBackClientHyperlink(_singleClickButton, "");
        // To prevent the first click from posting back immediately

        // (therefore giving the user a chance to double click) 

    // pause the postbackfor 300 milliseconds by 

        // wrapping the postback command in a setTimeout

        _jsSingle = _jsSingle.Insert(11, "setTimeout(\"");
        _jsSingle += "\", 300)";
        // Add this javascript to the onclick Attribute of the row

        e.Row.Attributes["onclick"] = _jsSingle;

        // Get the LinkButton control in the second cell

        LinkButton _doubleClickButton = (LinkButton)e.Row.Cells[1].Controls[0];
        // Get the javascript which is assigned to this LinkButton

        string _jsDouble = 
        ClientScript.GetPostBackClientHyperlink(_doubleClickButton, "");
        // Add this javascript to the ondblclick Attribute of the row

        e.Row.Attributes["ondblclick"] = _jsDouble;
    }
}

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

    

<Columns>
    <asp:ButtonField Text="SingleClick" CommandName="SingleClick" 
                            Visible="false" />
    <asp:ButtonField Text="DoubleClick" CommandName="DoubleClick" 
                            Visible="false" />
</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".

 

   
protected override void Render(HtmlTextWriter writer)
{
    foreach (GridViewRow r in GridView1.Rows)
    {
        if (r.RowType == DataControlRowType.DataRow)
        {
            Page.ClientScript.RegisterForEventValidation
                    (r.UniqueID + "$ctl00");
            Page.ClientScript.RegisterForEventValidation
                    (r.UniqueID + "$ctl01");
        }
    }

    base.Render(writer);
}


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


    结论

      通过JS与ASP.NET的紧密结合,我们可以扩展GridView和DataList的功能。为了你的程序的安全,如果可以的话,你不应该将EnableEventValidation="false" 。一旦你理解了EventValidation是如何工作的,你可以使用ClientScript.RegisterForEventValidation却包你的代码执行的更安全


   

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值