从ASP.NET GridView中获取一个DataRow

3
我有一个绑定到ObjectDataSource(该数据源绑定到MySQL数据库)的 ASP.NET GridView。在这个网格中,我有2个未绑定的ButtonField列,我想触发服务器端事件。因此,我添加了一个事件处理程序方法到GridViewRowCommand事件。
在该事件处理程序的代码中,我需要以某种方式获取用户单击的底层DataRow。但是,我似乎无法使其工作;如果我使用以下代码,selectedRow变量始终为null:
protected void searchResultsGridView_RowCommand(object sender, GridViewCommandEventArgs e)
{
  CallDataRow selectedRow = (CallDataRow) searchResultsGridView.Rows[Convert.ToInt32(e.CommandArgument)].DataItem;
}

我已经谷歌搜索并找到了类似http://ranafaisal.wordpress.com/2008/03/31/how-to-get-the-current-row-in-gridview-row-command-event的页面,但是我找到的所有内容都不起作用。我相信我只是缺少一些明显的东西,但是我无法弄清楚是什么...
如果可以,请看一下以下ASP.NET代码:
  <asp:GridView ID="searchResultsGridView" runat="server" AutoGenerateColumns="False" 
    DataKeyNames="PersonNo,CallDate" 
    Width="100%" AllowPaging="True" EnableSortingAndPagingCallbacks="True" 
    onrowcommand="searchResultsGridView_RowCommand" PageSize="20">
    <Columns>
      <asp:BoundField DataField="PersonNo" HeaderText="Account number" ReadOnly="True" 
        SortExpression="PersonNo" />
      <asp:BoundField DataField="AgentNo" HeaderText="Agent number" 
        SortExpression="AgentNo" />
      <asp:BoundField DataField="AgentName" HeaderText="Agent name" 
        SortExpression="AgentName" />
      <asp:BoundField DataField="TelNumber" HeaderText="Telephone number" 
        SortExpression="TelNumber" />
      <asp:BoundField DataField="CallDate" HeaderText="Call date/time" ReadOnly="True" 
        SortExpression="CallDate" />
      <asp:ButtonField CommandName="play" HeaderText="Audio" ShowHeader="True" 
        Text="Play" />
      <asp:ButtonField CommandName="download" Text="Download" />
    </Columns>
  </asp:GridView>
5个回答

5

通过以下步骤最终使其工作:

  1. Adding a TemplateField containing a bound HiddenField.

    <asp:TemplateField ShowHeader="False">
      <ItemTemplate>
        <asp:HiddenField ID="audioFileName" runat="server" Value='<%# Eval("AudioFileName") %>' />
      </ItemTemplate>
    </asp:TemplateField>
    
  2. Adding the following code in the RowCommand event handler:

    protected void searchResultsGridView_RowCommand(object sender, GridViewCommandEventArgs e)
    {
      string audioFile = ((HiddenField) searchResultsGridView.Rows[Convert.ToInt32(e.CommandArgument)].FindControl("audioFileName")).Value;
    }
    

这是一种不太安全的临时解决方案,但它能够正常工作,目前这就是我所需要的。当然,如果有更好的解决方案,我仍然欢迎。


你尝试过没有使用“隐藏字段”这种解决方案吗? - Kiquenet

3

我来晚了!但是由于我从谷歌搜索中找到这里,因此可能仍有人会查看,所以我将提供我的答案:

protected void SomeDataGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
   if (e.Row.RowType == DataControlRowType.DataRow)
   {
       System.Data.DataRowView dr = (System.Data.DataRowView)e.Row.DataItem;
       string aVar = dr["DataFieldIdLikePlease"].ToString();
   }
}

那么你就可以在代码后端获取任何数据字段。

1

我知道这已经晚了2.5年(抱歉!之前没看到...),但我使用了两个静态/共享方法来直接转换行。也许这就是你想要做的?

VB.Net:

Public Shared Function GridViewRowToDataRow(ByVal gvr As GridViewRow) As DataRow
    Dim di As Object = Nothing
    Dim drv As DataRowView = Nothing
    Dim dr As DataRow = Nothing

    If gvr IsNot Nothing Then
        di = TryCast(gvr.DataItem, System.Object)
        If di IsNot Nothing Then
            drv = TryCast(di, System.Data.DataRowView)
            If drv IsNot Nothing Then
                dr = TryCast(drv.Row, System.Data.DataRow)
            End If
        End If
    End If

    Return dr
End Function

Public Shared Function GridViewRowEventArgsToDataRow(ByVal e As GridViewRowEventArgs) As DataRow
    Dim gvr As GridViewRow = Nothing
    Dim di As Object = Nothing
    Dim drv As DataRowView = Nothing
    Dim dr As DataRow = Nothing

    If e.Row.RowType = DataControlRowType.DataRow Then
        gvr = TryCast(e.Row, System.Web.UI.WebControls.GridViewRow)
        dr = Helpers.GridViewRowToDataRow(gvr)
    End If

    Return dr
End Function

C#.Net(转换使用:http://www.developerfusion.com/tools/convert/vb-to-csharp/):

public static DataRow GridViewRowToDataRow(GridViewRow gvr)
{
    object di = null;
    DataRowView drv = null;
    DataRow dr = null;

    if (gvr != null) {
        di = gvr.DataItem as System.Object;
        if (di != null) {
            drv = di as System.Data.DataRowView;
            if (drv != null) {
                dr = drv.Row as System.Data.DataRow;
            }
        }
    }

    return dr;
}

public static DataRow GridViewRowEventArgsToDataRow(GridViewRowEventArgs e)
{
    GridViewRow gvr = null;
    object di = null;
    DataRowView drv = null;
    DataRow dr = null;

    if (e.Row.RowType == DataControlRowType.DataRow) {
        gvr = e.Row as System.Web.UI.WebControls.GridViewRow;
        dr = Helpers.GridViewRowToDataRow(gvr);
    }

    return dr;
}

请勿在 void GridResultados_RowCommand(Object sender, GridViewCommandEventArgs e) 事件中使用。 - Kiquenet

1
 int index = Convert.ToInt32(e.CommandArgument);

 GridViewRow row = searchResultsGridView.Rows[index];

2
这给了我一个 RowType == DataRow 且 DataItem == null 的 GridViewRow。由于我需要 DataItem 才能获取基础 DataRow,而在这种情况下 DataItem 为 null,因此这不是一个答案。 - Ian Kemp

0
一种干净的方法是在GridView上使用"DataKeyNames"属性。数据源应该包含一个唯一标识符或主键列。然后,您可以将Gridview上的DataKeyNames属性设置为该属性的名称。
所选行对应的该列的值随后在RowCommand中可用,并且可以用于确保命令适用于唯一标识的对象。
<asp:GridView ID="gridview" runat="server" ... DataKeyNames="pkey">


protected void gridview_OnRowCommand(object sender, EventArgs e)        
{
    string selectedPkey = null;
    GridViewCommandEventArgs  gridEvent = (GridViewCommandEventArgs)e;
    int index = Convert.ToInt32(gridEvent.CommandArgument);
    if (index >= 0 && index < gridview.Rows.Count)
    {
        GridViewRow r = gridview.Rows[index];
        selectedPkey = gridview.DataKeys[index].Value.ToString();
    }

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