简体   繁体   English

ASP.NET C# Gridview 抛出索引超出范围

[英]ASP.NET C# Gridview throwing Index out of range

Im working on a user control that shows available stores from an SQL table on a gridview for the user to select and fill up a textbox.我正在开发一个用户控件,该控件显示来自网格视图上的 SQL 表的可用存储,供用户选择和填充文本框。 Currently im able to databind everything correctly to the gridview and run actions with the select button inside each row.目前我能够将所有内容正确地数据绑定到 gridview 并使用每行内的选择按钮运行操作。 My current problem is that i can't get to return the cell value into a variable when using "rows[index]".我目前的问题是使用“rows [index]”时我无法将单元格值返回到变量中。 When i reach this i get an Index is out of range error even if my index value is correct while debugging.当我达到这一点时,即使我的索引值在调试时是正确的,我也会得到一个 Index is out of range 错误。 For experiment purpose i gave the index a manual value of 0 and 1 on different iterations and i still get the error as if my gridview didn't contain any rows.出于实验目的,我在不同的迭代中为索引手动设置了 0 和 1 值,但我仍然得到错误,就好像我的 gridview 不包含任何行一样。

My method to select the row is using a Gridview with an OnRowCommand triggered by a ButtonField.我选择行的方法是使用带有由 ButtonField 触发的 OnRowCommand 的 Gridview。

Looking at some other similar questions and answers i found that most of the problems where around people getting negative values or not using DataKeyNames but this is not my case.查看其他一些类似的问题和答案,我发现大多数问题是人们获得负值或不使用 DataKeyNames,但这不是我的情况。 I still can't fix this error我仍然无法修复此错误

My gridview code is this:我的gridview代码是这样的:

<asp:GridView ID="gvStore" runat="server" AutoGenerateColumns="False" Visible="false" DataKeyNames="Name" OnRowCommand="gvExecSelectSTR_RowCommand">
            <Columns>            
                <asp:BoundField DataField="Name" HeaderText="Name" />            
                <asp:ButtonField ButtonType="Link" Text="Select" CommandName="SelectStore"/> 
            </Columns>
        </asp:GridView>

My button action我的按钮操作

protected void gvExecSelectSTR_RowCommand(object sender, GridViewCommandEventArgs e)
        {
            if (e.CommandName == "SelectStore")
            {
                int index = Convert.ToInt32(e.CommandArgument); //Up to this point i get correct row number for index
                GridViewRow row = gvStore.Rows[index]; //This row triggers my error
                IDStore.Text = row.Cells[0].Text;
            }
        }

Additionally, this is the method im using to databind everything to my GridView此外,这是我用来将所有内容数据绑定到我的 GridView 的方法

private void GridViewStore()
        {
            try
            {
                DataTable StoreTable = new DataTable();
                StoreTable.Columns.AddRange(new DataColumn[1]
                {
                    new DataColumn("Name",typeof(string))                    
                });

                //Can't show internal SQL commands for this but here i read and load
 the SQLscript that selects the table and load it into the reader variable "readerStore"//

                if (readerStore.HasRows)
                {
                    while (readerStore.Read())
                    {  
                        StoreTable.Rows.Add(readerStore["Name"].ToString());                            
                    }
                }
                gvStore.DataSource = StoreTable;
                gvStore.DataBind();
                readerStore.Close();
            }
            catch (Exception ex)
            {
                OnErrorOccurred(new ErrorOccurredEventArgs("Grid View Bind Message" + ex.Message, ex));
            }
        }

Is there anything im setting up wrong?我有什么设置错误吗?

Have you tried instead of你试过而不是

 GridViewRow row = gvStore.Rows[index];

Doing this这样做

 GridViewRow row = (GridViewRow)gvStore.Rows[e.RowIndex];  

why bother with row command?为什么要打扰行命令? You really don't need that event model, and in most cases, it just causes EXTRA pain.你真的不需要那个事件模型,而且在大多数情况下,它只会导致额外的痛苦。

And if you have a row PK id that you need on button click?如果您在单击按钮时需要一个行 PK id? Then use datakeys.然后使用数据键。 Datakeys is VERY nice for several reasons. Datakeys 非常好有几个原因。

For tops on the list, it always a HUGE security hole to expose data base PK's to the client side.对于列表中的顶部,将数据库 PK 暴露给客户端总是一个巨大的安全漏洞。 (the markup can be messed with, and thus the database ID you use now could be anything that was changed in the markup. (标记可能会被弄乱,因此您现在使用的数据库 ID 可能是标记中更改的任何内容。

So, simple grid view say like this:所以,简单的网格视图是这样说的:

        <asp:GridView ID="GHotels" runat="server" CssClass="table" AutoGenerateColumns="false"
            width="50%" DataKeyNames="ID" >
            <Columns>
                <asp:BoundField DataField="FirstName" HeaderText="FirstName"  />
                <asp:BoundField DataField="LastName" HeaderText="LastName"    />
                <asp:BoundField DataField="HotelName" HeaderText="HotelName"  />
                <asp:BoundField DataField="Description" HeaderText="Description" ItemStyle-Width="270" />

                <asp:TemplateField HeaderText = "View" ItemStyle-HorizontalAlign ="Center" >
                    <ItemTemplate>
                    <asp:Button ID="cmdRow" runat="server" Text="View" 
                       CssClass="btn"  />
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>

Note the data keys setting in above "ID" is our row PK id, and VERY nice is we do not have, display, show the PK row id in the markup at ANY time!!!请注意,上面“ID”中的数据键设置是我们的行 PK id,非常好的是我们没有,显示,随时在标记中显示 PK 行 id !!!

And code to fill then is this:然后要填写的代码是这样的:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            LoadData();
    }

    void LoadData()
    {
        using (SqlConnection conn = new SqlConnection(Properties.Settings.Default.TEST4))
        {
            string strSQL = 
                "SELECT * FROM tblHotelsA ORDER BY HotelName";
            using (SqlCommand cmdSQL = new SqlCommand(strSQL, conn))
            {
                DataTable rstData = new DataTable();
                conn.Open();
                rstData.Load(cmdSQL.ExecuteReader());
                GHotels.DataSource = rstData;
                GHotels.DataBind();
            }
        }
    }

And we now have this:我们现在有了这个:

在此处输入图像描述

Now, we need a click event for the button.现在,我们需要一个按钮的点击事件。 For most buttons, you can just double click on the button to add/wire up a event.对于大多数按钮,您只需双击按钮即可添加/连接事件。 However, since the button is inside of the GV, then we can't do that.但是,由于按钮在 GV 内部,所以我们不能这样做。 But we can still add the event by markup.但是我们仍然可以通过标记添加事件。

So, in the markup type in onclick="" when you do this, intel-sense will pop up the option to create the event.因此,在 onclick="" 的标记类型中执行此操作时,intel-sense 会弹出创建事件的选项。 Say like this:像这样说:

在此处输入图像描述

(under the quotes, hit ctrl-space to pop that intel-sense dialog). (在引号下,按 ctrl-space 以弹出该 Intel-sense 对话框)。

Ok, choose create new event.好的,选择创建新事件。

Now, flip to code behind, there should be a simple click event for that button.现在,翻到后面的代码,该按钮应该有一个简单的单击事件。

So, with this code:因此,使用此代码:

    protected void cmdRow_Click(object sender, EventArgs e)
    {
        Button btn = sender as Button;
        GridViewRow gRow = btn.NamingContainer as GridViewRow;

        Debug.Print("Row index click = " + gRow.RowIndex);
        Debug.Print("ID (data keys) = " + GHotels.DataKeys[gRow.RowIndex]["ID"].ToString());
        Debug.Print("FirstName = " + gRow.Cells[0].Text);
        Debug.Print("Last Name = " + gRow.Cells[1].Text);
    }

Output:输出:

在此处输入图像描述

So, with this simple setup:因此,通过这个简单的设置:

If I have multiple buttons on the GV, then a get a nice simple SEPERATE click event and code stub.如果我在 GV 上有多个按钮,那么可以获得一个简单的单独单击事件和代码存根。 No messy row command (to then check some row command arugment).没有凌乱的行命令(然后检查一些行命令参数)。

I get the row index with ease.我很容易得到行索引。

I get the code behind NEVER exposed data base PK id (from datakeys)我得到了从不暴露数据库 PK id 背后的代码(来自 datakeys)

I am free to get/grab any cell value from the current row.我可以自由地从当前行获取/抓取任何单元格值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM