将控件动态添加到 gridview 后,无法再访问控件或 gv.selectedvalue

after dynamically adding controls to a gridview, can no longer access controls or gv.selectedvalue

我在 gv.DataBinding 事件中向 gridview 动态添加一些字段。我在 C# 中处理选择、分页和排序。一切都在屏幕上正确呈现,我可以看到数据已加载到 gridview 中。

<asp:GridView ID="gvPulledBills" runat="server" AutoGenerateColumns="false" 
    OnDataBinding="gvPulledBills_DataBinding" OnRowDataBound="gvPulledBills_RowDataBound" 
    OnSelectedIndexChanged="gvPulledBills_SelectedIndexChanged"  
    AllowSorting="true" OnSorting="gvPulledBills_Sorting" 
    AllowPaging="true" PageSize="30" OnPageIndexChanging="gvPulledBills_PageIndexChanging"
    DataKeyNames="Id" SkinID="gridviewGray">

在 gv.SelectedIndexChanged 事件中,我需要检索所选行的 ID。 ID 存储在 HiddenField 中,gv.DataKeyNames 值设置为 ID,因此我有两种方法来检索它。

gv.SelectedValue 在初始渲染后工作正常。但是,当在paging/sorting之后选择一行时,gv.SelectedValue returns null。它的行为就好像根本没有选择任何东西,即使我选择的行标记工作正常。关于动态绑定列时我需要做什么以确保数据键可检索的任何建议?

或者,我尝试直接访问隐藏字段而不是依赖于 gv.SelectedValue...

protected void gvPulledBills_SelectedIndexChanged(object sender, EventArgs e)
{
    GridView gv = (GridView)sender;
    //var key = (int)gv.SelectedValue;
    var index = gv.SelectedIndex - (gv.PageIndex * gv.PageSize);
    var row = gv.Rows[index];
    var hiddenField = (HiddenField)row.FindControl("hdnId");
    var key = int.Parse(hiddenField.Value);
    ...
}

但是控件集合在每个单元格中都是空的,即使对于显式声明的字段也是如此,即使屏幕上有数据也是如此。 显式声明

<Columns>
    <asp:TemplateField>
        <ItemTemplate>
            <asp:HiddenField ID="hdnId" runat="server" Value='<%# Eval("Id") %>' />
        </ItemTemplate>
    </asp:TemplateField>
</Columns>

动态声明

private TemplateField CreateTemplateField()
{
    var controls = new List<Control>
    {
        { CreateHiddenIdField() }
    };
    var tf = GridViewTools.CreateTemplateField(string.Empty, string.Empty, controls);
    tf.ItemStyle.CssClass = "noRightBorder";
    tf.HeaderStyle.CssClass = "noBorder";
    return tf;
}
private static Control CreateHiddenIdField()
{
    var hdn = new HiddenField();
    hdn.ID = "hdnId";
    hdn.Value = "'<%# Eval(\"Id\") %>'";
    return hdn;
}
//in static class GridViewTools
public static TemplateField CreateTemplateField(string headerText, string sortExpression, List<Control> controls)
    {
        TemplateField tf = new TemplateField();
        tf.HeaderText = headerText;
        tf.SortExpression = sortExpression;
        tf.ItemTemplate = new GridViewTemplate(DataControlRowType.DataRow, controls);

        return tf;
    }

//... snippet that adds column to grid
    var addColumns = new List<DataControlField>();        
    addColumns.Add(CreateTemplateField());
    // add other columns
    foreach (var column in addColumns)
    {
        gv.Columns.Add(column);
    }
//...

有没有人对在 paging/sorting 后面的代码与动态列一起使用时如何填充 SelectedValue 有任何建议?或者关于如何确保动态创建的字段控件在代码隐藏中被填充和访问的任何建议?

我添加了更多列,主要是绑定字段。我这样做是为了根据页面其他地方的下拉字段自定义列集。总共大约有 30 列,我不想将它们全部添加到 gridview,而不仅仅是设置它们的可见性。

更新解决方案 最终的解决方案是:

var gv = (GridView)sender;
var rowIndex = gv.SelectedIndex - (gv.PageIndex * gv.PageSize);
var key = (int)gv.DataKeys[rowIndex]["Id"];
DisplayWorkDetail(key);

SelectedRowSelectedValue 此时为空。仅填充 SelectedIndex。通过将 SelectedIndex 转换为 RowIndex,我能够直接从行中检索 DataKey。

我选择使用 sender 来使代码通用,这样我就可以轻松地将它提取到与其他 GridView 一起使用的方法中。

我认为你不能在这里使用发件人。

但是,虽然 Rowcommand 没有更改选定的索引,但在该索引更改事件中,它已经更改。所以,你可以直接use/reference控制

例如:

       GridViewRow myGv As GridViewRow = gvPulledBills.SelectedRow

然后: myGv.RowIndex(get/use 行索引)。

但是,您已经有了该行,所以:

   hiddenField myField = (HiddenField)myGv.FindControl("hdnId");
   
   int MyKey = int.Parse(myField.Value);

我想你也可以使用 Datakeys 集合,甚至没有那个隐藏字段。

所以,你可以这样做:

  GridViewRow myGv As GridViewRow = gvPulledBills.SelectedRow

  int RowPK = (int)(gvPulledBills.DataKeys[myGv.RowIndex]["ID"]);