Solved

Index was out of range. Must be non-negative and less than the size of the collection.

Posted on 2008-06-20
6
2,665 Views
Last Modified: 2013-12-16
Hi Experts,

I am having the following error in my code... there is a gridview and each row on it has a "delete" button which executes the following code:

    protected void GridView_userList_SelectedIndexChanged(object sender, EventArgs e)
    {
        // Get User_ID of selected row
 
        int nRecipUser_ID = Convert.ToInt16(((Label)GridView_userList.SelectedRow.FindControl("lblRecipUser_ID")).Text);

        // Remove user from nomination
        RecipientManager.recipient_DeleteFromOrder(nRecipUser_ID, SessionManager.Instance.nNomination_ID);
    }

This works fine when deleting items from the gridview except the very last item, which causes an error:

Index was out of range. Must be non-negative and less than the size of the collection.

The highlighted line error is:

Line 103:        int nRecipUser_ID = Convert.ToInt16(((Label)GridView_userList.SelectedRow.FindControl("lblRecipUser_ID")).Text);

Any ideas?!

Thanks,

Anthony



0
Comment
Question by:gthendry
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
6 Comments
 
LVL 21

Expert Comment

by:naspinski
ID: 21830441
Sounds like you are not deleting the correct row.  The rows are zero indexed, so if the row is 10 items long, 9 is the last item.

Are you sure you are deleting the correct rows?  Try this maybe?
int nRecipUser_ID = Convert.ToInt16(((Label)GridView_userList.SelectedRow.FindControl("lblRecipUser_ID")).Text)-1;

Open in new window

0
 

Author Comment

by:gthendry
ID: 21830900
Hi,

I'm sure it is correct because the ID it is retrieving is the text value of the label control which in turn is the ID of the database record, not the id of the row.

But I did find a mistake... I was choosing the nRecipUser_ID which was not the primary key for the Recipients table where my data is coming from for this gridview... I have now changed it to nRecipient_ID which is the primary key but I'm still having the same problem but also another problem. When I click the select button on the first gridview (gridview_SearchResults), I am not seeing the user appear in my 2nd gridview (GridView_userList) UNLESS I click TWICE on the "select" button in the first gridview.

Just to explain what this page is supposed to do...

1) User enters some search values into textboxes, then the search results appear in a gridview. Each row in that gridview has a select button.
2) When the select button is clicked, the page checks if there is an order session. If yes, then the recipient is added to the recipients table in database along with the existing order ID (in session)
3) If the order ID does not exist in session, then a new order is created and the order id is stored in a session. Then the recipient is added to this order as above.
4) Each time the page is loaded, the page checks to see if there is an existing order session ID. If there is, then the 2nd gridview is displayed (this one retrieves any recipients that have been added to this order). Each row in this gridview has a Delete button next to it, which when clicked, should remove the recipient from the recipients table in the database.


Here is all my code for this page:

   
<%@ Page Language="C#" MasterPageFile="~/Pages/MasterPage.master" AutoEventWireup="true"
    CodeFile="search.aspx.cs" Inherits="Pages_nominate_search" Title="Untitled Page" %>
 
<asp:Content ID="Content1" ContentPlaceHolderID="mainContent" runat="Server">
    <div>
        <div id="contentWrap">
            <div id="colOne">
                <div id="subNav">
                </div>
            </div>
            <div id="colTwo">
                <div id="titleArea2">
                    <img src="../../Assets/images/titles/nominate_chooserecipient.gif" alt="Choose a recipient" /></div>
                <div id="textArea_wide">
                    <h1>
                        New Search</h1>
                    <p>
                        Enter the first or last name of the person you would like to nominate, choose whether
                        they are Team or Individual nominees and click <b>Search</b></p>
                    <p>
                        Partial entry will return wider results - e.g. entering just the first letter of
                        a surname will return all people with surnames beginning with that letter. You can
                        also filter on Business Unit, using the drop-down box provided.</p>
                    <table border="0" cellspacing="0" cellpadding="10" class="table1">
                        <tr>
                            <td>
                                <table cellspacing="0" cellpadding="4" border="0">
                                    <tr>
                                        <td>
                                            <b>Type of Nominees</b>
                                        </td>
                                        <td>
                                            <asp:RadioButton ID="radIndividual" GroupName="RecipientType" runat="server" Checked="true" />
                                            Individual
                                            <asp:RadioButton ID="radTeam" GroupName="RecipientType" runat="server" />
                                            Team
                                        </td>
                                    </tr>
                                    <tr>
                                        <td>
                                            <b>Preferred Name</b>
                                        </td>
                                        <td>
                                            <asp:TextBox ID="txtForename" runat="server"></asp:TextBox>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td>
                                            <b>Last Name</b>
                                        </td>
                                        <td>
                                            <asp:TextBox ID="txtSurname" runat="server"></asp:TextBox>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td>
                                            <b>Business Unit</b>
                                        </td>
                                        <td>
                                            <asp:DropDownList ID="ddlBusinessUnit" runat="server">
                                            </asp:DropDownList>
                                        </td>
                                    </tr>
                                    <tr>
                                        <td colspan="2">
                                            <asp:Button ID="btnSearch" runat="server" OnClick="btnSearch_Click" Text="Search" />
                                        </td>
                                    </tr>
                                </table>
                            </td>
                        </tr>
                    </table>
                    <br />
                    <asp:Panel ID="panel_SearchResults" runat="server" Visible="False">
                        <asp:GridView ID="GridView_SearchResults" runat="server" AutoGenerateColumns="False"
                            DataSourceID="objdatasource_usersearch" HeaderStyle-CssClass="hc" CssClass="table2"
                            HeaderStyle-HorizontalAlign="Left" OnSelectedIndexChanged="GridView_SearchResults_SelectedIndexChanged">
                            <Columns>
                                <asp:TemplateField HeaderText="nUser_ID" Visible="false">
                                    <ItemTemplate>
                                        <asp:Label ID="lblUser_ID" runat="server" Text='<%#Eval("nUser_ID") %>' />
                                    </ItemTemplate>
                                </asp:TemplateField>
                                <asp:TemplateField HeaderText="Name" HeaderStyle-Width="200">
                                    <ItemTemplate>
                                        <%# Eval("sForename") %>
                                        <%# Eval("sSurname") %>
                                    </ItemTemplate>
                                    <HeaderStyle Width="200px" />
                                </asp:TemplateField>
                                <asp:BoundField DataField="sUserfield1" HeaderText="Business Unit" SortExpression="sUserfield1" />
                                <asp:BoundField DataField="sEmail" HeaderText="Email" SortExpression="sEmail" />
                                <asp:CommandField HeaderText="" ShowSelectButton="True" ButtonType="Button" />
                            </Columns>
                            <HeaderStyle CssClass="hc" />
                        </asp:GridView>
                    </asp:Panel>
                    <asp:ObjectDataSource ID="objdatasource_usersearch" runat="server" DataObjectTypeName="DES.Quantum.BO.Employee"
                        OldValuesParameterFormatString="original_{0}" SelectMethod="GetUserList" TypeName="DES.Quantum.BLL.EmployeeManager">
                        <SelectParameters>
                            <asp:ControlParameter ControlID="txtForename" Name="sForename" Type="String" DefaultValue="" />
                            <asp:ControlParameter ControlID="txtSurname" Name="sSurname" Type="String" DefaultValue="" />
                            <asp:ControlParameter ControlID="ddlBusinessUnit" Name="sBusinessUnit" Type="String"
                                DefaultValue="" />
                        </SelectParameters>
                    </asp:ObjectDataSource>
                    <br />
                    <asp:Panel ID="Panel_userList" runat="server" Visible="False">
                    </asp:Panel>
                    <br />
                    <asp:ObjectDataSource ID="objdatasource_userList" runat="server" DataObjectTypeName="DES.Quantum.BO.Recipient"
                        OldValuesParameterFormatString="original_{0}" SelectMethod="GetRecipientList" TypeName="DES.Quantum.BLL.RecipientManager">
                        <SelectParameters>
                            <asp:Parameter Name="nOrder_ID" Type="Int32" />
                        </SelectParameters>
                    </asp:ObjectDataSource>
                    <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
                    <asp:GridView ID="GridView_userList" runat="server" AutoGenerateColumns="False" DataSourceID="objdatasource_userList"
                        HeaderStyle-CssClass="hc" CssClass="table2" OnSelectedIndexChanged="GridView_userList_SelectedIndexChanged">
                        <Columns>
                            <asp:TemplateField HeaderText="nRecipient_ID" Visible="false">
                                <ItemTemplate>
                                    <asp:Label ID="lblRecipient_ID" runat="server" Text='<%#Eval("nRecipient_ID") %>' />
                                </ItemTemplate>
                            </asp:TemplateField>
                            <asp:TemplateField HeaderText="Name" HeaderStyle-Width="200">
                                <ItemTemplate>
                                    <%# Eval("sForename") %>
                                    <%# Eval("sSurname") %>
                                </ItemTemplate>
                                <HeaderStyle Width="200px" />
                            </asp:TemplateField>
                            <asp:BoundField DataField="sUserfield1" HeaderText="Business Unit" SortExpression="sUserfield1" />
                            <asp:BoundField DataField="sEmail" HeaderText="Email" SortExpression="sEmail" />
                            <asp:CommandField HeaderText="" ShowSelectButton="True" ButtonType="Button" SelectText="Remove" />
                        </Columns>
                        <HeaderStyle CssClass="hc"></HeaderStyle>
                    </asp:GridView>
                </div>
            </div>
        </div>
        <br clear="all" />
    </div>
</asp:Content>
 
 
======== CODE BEHIND =============
 
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
 
using DES.Quantum.BO;
using DES.Quantum.BLL;
 
public partial class Pages_nominate_search : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        // Bind drop down for business units
        if (!IsPostBack)
        {
            loadBusinessUnits();
        }
 
        // Bind Datagrid to show current users in nomination
        if (SessionManager.Instance.nNomination_ID != 0)
        {
            Panel_userList.Visible = true;
            objdatasource_userList.SelectParameters.Clear();
            objdatasource_userList.SelectParameters.Add("nOrder_ID", SessionManager.Instance.nNomination_ID.ToString());
            GridView_userList.DataBind();
        }
    }
 
    protected void loadBusinessUnits()
    {
        DataSet ds = NominationManager.GetBusinessUnits();
        ddlBusinessUnit.DataSource = ds;
        ddlBusinessUnit.DataTextField = "sUserfield1";
        ddlBusinessUnit.DataValueField = "sUserfield1";
        ddlBusinessUnit.DataBind();
        ListItem item = new ListItem();
        item.Value = "";
        item.Text = "Please select...";
        
        ddlBusinessUnit.Items.Insert(0, item);
    }
 
 
    protected void btnSearch_Click(object sender, EventArgs e)
    {
        panel_SearchResults.Visible = true;
        //GridView_SearchResults.DataSource = objdatasource_usersearch;
        GridView_SearchResults.DataBind();
    }
    protected void GridView_SearchResults_SelectedIndexChanged(object sender, EventArgs e)
    {
        // Get User_ID of selected row
        int nUser_ID = Convert.ToInt16(((Label)GridView_SearchResults.SelectedRow.FindControl("lblUser_ID")).Text);
 
        //Check if nomination exists, if not, then create new nomination
        if (SessionManager.Instance.nNomination_ID == 0)
        {
            // Create new nomination
            int nNomination_ID = NominationManager.InsertNomination(SessionManager.Instance.nUser_ID);
            Nomination myNomination = NominationManager.GetNomination(nNomination_ID);
 
            //Save nomination ID in Session
            SessionManager.Instance.nNomination_ID = myNomination.nOrder_ID;
 
            //Add Recipient To order
            addEmployeeToOrder(nUser_ID);
            
            Label1.Text = myNomination.nOrder_ID.ToString();
            
        }
        else
        {
            if (nUser_ID <= 0) throw new ApplicationException("Invalid User ID");
 
            //Add Recipient To order
            addEmployeeToOrder(nUser_ID);
 
            Label1.Text = "Add";
        }
        
    }
 
    protected void addEmployeeToOrder(int nUser_ID)
    {
        // Add recipient to current nomination
        Employee myEmployee = EmployeeManager.GetUserByID(nUser_ID);
        int nNomination_ID = (int)SessionManager.Instance.nNomination_ID;
        RecipientManager.recipient_AddToOrder(myEmployee, SessionManager.Instance.nNomination_ID);
    }
 
    protected void GridView_userList_SelectedIndexChanged(object sender, EventArgs e)
    {
        // Get User_ID of selected row
 
        int nRecipient_ID = Convert.ToInt16(((Label)GridView_userList.SelectedRow.FindControl("lblRecipient_ID")).Text);
 
        // Remove user from nomination
        RecipientManager.recipient_DeleteFromOrder(nRecipient_ID);
    }
}

Open in new window

0
 

Author Comment

by:gthendry
ID: 21831345
Hi,

I seem to have fixed the problem for the "index out of range" error by doing the following:

1) Added "DataKeyNames="nRecipient_ID" to the GridView control for the User_List (the 2nd gridview in my example)
2) Modified the SelectedIndexChanged event on the gridview to use the datakey as follows:

===

protected void GridView_userList_SelectedIndexChanged(object sender, EventArgs e)
    {
        // Get User_ID of selected row

        //int nRecipient_ID = Convert.ToInt16(((Label)GridView_userList.SelectedRow.FindControl("lblRecipient_ID")).Text);
        int nRecipient_ID = (int)GridView_userList.SelectedDataKey.Values["nRecipient_ID"];

        // Remove user from nomination
        RecipientManager.recipient_DeleteFromOrder(nRecipient_ID);

        // Databind
        GridView_userList.DataBind();
    }

I'm still getting the problem of having to click "select" button twice on the first gridview before the 2nd one is updated which is strange...

Any suggestions for points???

Cheers,

Anthony

0
Is Your DevOps Pipeline Leaking?

Is your CI/CD pipeline a hodge-podge of randomly connected tools? You’ve likely got a tool to fix one problem & then a different tool to fix another, resulting in a cluster of tools with overlapping functionality. Learn how to optimize your pipeline with Gartner's recommendations

 

Author Comment

by:gthendry
ID: 21831643
I think I've fixed the "clicking twice" issue as well. Essentially I had to re-bind the user_list gridview inside the selectedindexchanged event of the first gridview... eg.

            Panel_userList.Visible = true;
            objdatasource_userList.SelectParameters.Clear();
            objdatasource_userList.SelectParameters.Add("nOrder_ID", SessionManager.Instance.nNomination_ID.ToString());
            GridView_userList.DataBind();

Cheers

Anthony

0
 
LVL 22

Accepted Solution

by:
prairiedog earned 500 total points
ID: 21831726
The problem is caused by the wrong logic of your code. Page_Load event handler always fires before the SelectedIndexChanged event handlers. Let's see your current logic:
1. Page is loaded, since there is no OrderID, so the second GridView will not be updated, and this block of code in Page_Load will be skipped:
    if (SessionManager.Instance.nNomination_ID != 0)
        {
            Panel_userList.Visible = true;
            objdatasource_userList.SelectParameters.Clear();
            objdatasource_userList.SelectParameters.Add("nOrder_ID", SessionManager.Instance.nNomination_ID.ToString());
            GridView_userList.DataBind();
        }
2. User clicks "Search" button, page is posted back. Still no update for the second GridView. Then the first GridView displays the search results. <====Pay attention the order of the two GridViews be processed.
3. The "select" button is clicked from the first GridView, page is posted back. Still no OrderID in session, so no update for the second GridView. Then the first GridView's SelectedIndexChanged event handler fires, the order ID is stored in session. <====Too late.
4. The "select" button is clicked AGAIN, page is posted back. This time, there is an order ID from step 3 in the session, so this block of code finally gets executed and the second GridView gets update.
if (SessionManager.Instance.nNomination_ID != 0)
        {
            Panel_userList.Visible = true;
            objdatasource_userList.SelectParameters.Clear();
            objdatasource_userList.SelectParameters.Add("nOrder_ID", SessionManager.Instance.nNomination_ID.ToString());
            GridView_userList.DataBind();
        }

That is why the update of the second GridView is always one-click behind.
Take the block of code above out of the Page_Load event handler and make it a function. Then in the first GridView's SelectedIndexChanged event handler, after you store the order ID in the sssion, call this function to update your second GridView.
0
 

Author Comment

by:gthendry
ID: 21831840
Thanks PrairieDog ... this is exactly what I did before you posted but since you gave a great step by step overview, I'll award you the points.

Thanks for taking the time to confirm what I thought was going on in the page :-)

Anthony
0

Featured Post

Space-Age Communications Transitions to DevOps

ViaSat, a global provider of satellite and wireless communications, securely connects businesses, governments, and organizations to the Internet. Learn how ViaSat’s Network Solutions Engineer, drove the transition from a traditional network support to a DevOps-centric model.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

For those of you who don't follow the news, or just happen to live under rocks, Microsoft Research released a beta SDK (http://www.microsoft.com/en-us/download/details.aspx?id=27876) for the Xbox 360 Kinect. If you don't know what a Kinect is (http:…
Introduction This article shows how to use the open source plupload control to upload multiple images. The images are resized on the client side before uploading and the upload is done in chunks. Background I had to provide a way for user…
There are cases when e.g. an IT administrator wants to have full access and view into selected mailboxes on Exchange server, directly from his own email account in Outlook or Outlook Web Access. This proves useful when for example administrator want…
If you’ve ever visited a web page and noticed a cool font that you really liked the look of, but couldn’t figure out which font it was so that you could use it for your own work, then this video is for you! In this Micro Tutorial, you'll learn yo…

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question