如何在GridView中实现无需选择按钮的全行选择?

29

我正在实现一个功能,当用户在GridView的行中的任意点上按下时,该行将被选择而不是选择按钮。

输入图像描述

为了实现这个功能,我使用以下代码:

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        // Set the hand mouse cursor for the selected row.
        e.Row.Attributes.Add("OnMouseOver", "this.style.cursor = 'hand';");

        // The seelctButton exists for ensuring the selection functionality
        // and bind it with the appropriate event hanlder.
        LinkButton selectButton = new LinkButton()
        {
            CommandName = "Select",
            Text = e.Row.Cells[0].Text
        };

        e.Row.Cells[0].Controls.Add(selectButton);
        e.Row.Attributes["OnClick"] =
             Page.ClientScript.GetPostBackClientHyperlink(selectButton, "");
    }
}

使用上述代码存在以下问题:

  • 仅当页面的EnableEventValidation设置为false时,才能正常工作。
  • SelectedIndexChanged仅在页面的Page_Load方法中调用Grid.DataBind()时(在每个postback中)才会触发。

我做错了什么吗?有更好的实现方法吗?


编辑:EnableEventValidation设置为true时,将出现以下错误:

Invalid postback or callback argument. Event validation is enabled using in configuration or <%@ Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.

5个回答

46

每次postback都必须添加此代码,而不仅仅是在数据绑定时。因此,您应该使用GridView的RowCreated事件。

例如:

(C#):

protected void GridView1_RowCreated(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow) {
        e.Row.Attributes["onmouseover"] = "this.style.cursor='pointer';this.style.textDecoration='underline';";
        e.Row.Attributes["onmouseout"] = "this.style.textDecoration='none';";
        e.Row.ToolTip = "Click to select row";
        e.Row.Attributes["onclick"] = this.Page.ClientScript.GetPostBackClientHyperlink(this.GridView1, "Select$" + e.Row.RowIndex);
    }
}

(VB.Net):

Private Sub GridView1_RowCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowCreated
    If e.Row.RowType = DataControlRowType.DataRow Then
        e.Row.Attributes("onmouseover") = "this.style.cursor='pointer';this.style.textDecoration='underline';"
        e.Row.Attributes("onmouseout") = "this.style.textDecoration='none';"
        e.Row.ToolTip = "Click to select row"
        e.Row.Attributes("onclick") = Me.Page.ClientScript.GetPostBackClientHyperlink(Me.GridView1, "Select$" & e.Row.RowIndex)
    End If
End Sub

这并不能解决将“EnableEventValidation”设置为false的问题。 - Amir Ismail
@Homam:你使用了我的代码,但仍然遇到“无效的postback/callback参数”错误吗?我在我的项目中无法重现此错误,但可能有其他原因。我现在没有时间进一步调查这个问题。您可以使用ClientScriptManager.RegisterForEventValidation来避免它。也许这个链接会有所帮助。 - Tim Schmelter
那是用什么语言来描述样式的?我尝试使用CSS,但似乎不起作用。例如,它不是background-color,而是backgroundColor。 - Despertar

13
RowCreated事件不如在Render()方法中完成操作,这样您可以使用带有true参数的GetPostBackClientHyperlink重载版本上的registerForEventValidation,从而避免“无效的回发/回调参数”错误。类似下面这样的操作:
protected override void Render(HtmlTextWriter writer)
    {
      foreach (GridViewRow r in GridView1.Rows)
      {
        if (r.RowType == DataControlRowType.DataRow)
        {
          r.Attributes["onmouseover"] = "this.style.cursor='pointer';this.style.textDecoration='underline';";
          r.Attributes["onmouseout"] = "this.style.textDecoration='none';";
          r.ToolTip = "Click to select row";
          r.Attributes["onclick"] = this.Page.ClientScript.GetPostBackClientHyperlink(this.GridView1, "Select$" + r.RowIndex,true);

        }
      }

      base.Render(writer);
    }

这也解决了我的问题。互联网上的所有其他帖子都告诉你禁用“EnableEventValidation”,这会使您的站点容易受到注入攻击,而这个才是真正的答案。 - Mr.K

3
<style type="text/css">
    .hiddenColumn
    {
        display: none;
    }

    .rowGrid
    {
        cursor: pointer;
    }
</style>

<asp:GridView runat="server" ID="GridView1" AutoGenerateColumns="true" >
            <RowStyle CssClass="rowGrid" />
            <Columns>
                <asp:CommandField ButtonType="Button" ShowSelectButton="true" HeaderStyle-CssClass="hiddenColumn"
                    ItemStyle-CssClass="hiddenColumn" FooterStyle-CssClass="hiddenColumn" />
            </Columns>
        </asp:GridView>

<script type="text/javascript">
        $(function () {
            $("#<%= GridView1.ClientID %> tr.rowGrid")
            .live("click", function (event) {
                $(this).find("input[type='button'][value='Select']").click();
            });

            $("#<%= GridView1.ClientID %> input[type='button'][value='Select']")
                .live("click", function (event) {
                    event.stopPropagation();
                });

        });
    </script>

0
尝试这个,在网格中添加OnSelectedIndexChanged事件。
   OnSelectedIndexChanged="Grid_SelectedIndexChanged"

然后在代码后台

 protected void Grid_SelectedIndexChanged(object sender, EventArgs e)
{
    GridViewRow row = gvSummary.SelectedRow;
    //Int32 myvalue= Convert.ToInt32(row.Attributes["ColumnName"].ToString());
   } 

并设置EnableViewState="false",但在这里您还需要执行两个已经在代码中完成的操作,即将EnableEventValidation设置为false,并在页面加载时进行Grid数据绑定。


-2
尝试在ASPX代码中使用<asp:LinkButton>将其包围在<tr>周围,设置LinkButton的CommandName='Select'。在项命令事件中处理此命令并设置所选行的样式!

1
你确定在 td 和 tr 之间放置 LinkButton 会生成有效的符合标准的 HTML 吗? - Davide Piras
@Davide Piras:问题中没有提到符合标准的HTML是必需的!如果这是一个要求,那就不要接受这个解决方案!我展示了一些可能性! - Numan
我不同意,我没有投票反对你,也不会这样做,但即使原帖中没有提到,我们现在已经是2011年夏季(几乎了),让我们只给出跨浏览器和完全兼容的答案吧 :) ;-) - Davide Piras
@Davide Piras:我不在意点踩!我完全同意您关于标准兼容性的观点!但是,我只是试图提供帮助!没有更多也没有更少!我曾经遇到过与 @Homan 类似的情况,但当时我必须尽快在生产服务器上让它工作。因此,当时无法考虑标准兼容性!;-) 我认为这个人也处于类似的情况中,并会从我当时的临时解决方案中受益。干杯! :-) - Numan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接