Michael Weston Michael Weston - 2 months ago 23
C# Question

ArgumentOutOfRangeException when looping with foreach and counter variable into ListView?

I have a multiselect OpenFileDialog which is looping through every line in multiple files and keeping count in order to do specific work by Index. How do I stop it from giving me an ArgumentOutOfRangeException when loading more than 1 file? Listview is already populated with items and subitems collection into two additional headers. The two files combined will only be loading about 6 items into column [1].

public void LoadStudents()
{
var ofdLoadStudents = new OpenFileDialog();
ofdLoadStudents.Multiselect = true;
int Counter = 0;

if (ofdLoadStudents.ShowDialog() == DialogResult.OK)
{
foreach (string studentList in ofdLoadStudents.FileNames)
{
foreach (string Students in File.ReadAllLines(studentList))
{
//[Period 1] | [ReadAllLines Data]
//listview already populated with 10 items, and subitems with "" as the item.
//only loading total of 6 lines with 2 files, into [1] column.
listViewStudents.Items[Counter].SubItems[1].Text = Students;
Counter++;
}
}
}
}

Answer

An "ArgumentOutOfRangeException" can be caused when attempting to access an element outside of an collection. For instance, let's say you have a List with 5 ints inside of it. Now, let's say you try to access element 7. There is no element seven, so you will get an ArgumentOutOfRangeException.

There are two places I see in your above code that could cause this problem, and they are both on the same line:

listViewStudents.Items[Counter].SubItems[1].Text = Students;

The first problem location is the listViewStudents.Items[Counter] part. The Items object in listViewStudents is a collection which must have objects added to it before accessing them. If you don't add any objects to "Items", or if your Counter variable gets too large you will try to access an element of the Items object which does not exist, so you will get the error. This is where I think the problem most likely is. Where are you adding items to the listViewStudents.Items collection? Is it somewhere else in your code? Make sure this is initialized before trying to access the elements. Also, if you are adding them somewhere else in your code, how do you know that the number of lines in the text file you are reading does not exceed the number of elements in the Items collection? These are the things you need to take in to account when dealing with any type of collection.

The second problem location is in the SubItems[1] part. SubItems is also a collection, and if it is not initialized with at least two elements (you're accessing the second element by calling SubItems[1], it starts with SubItems[0]) then you will also get an ArgumentOutOfRangeException.

So your problem is not with your foreach loops, they look fine.

EDIT:

I quickly wrote some code that implements what I think you're trying to do. Are you trying to read a list of student names and add them to a WinForm ListView control? If so, this code will do that.

public void LoadStudents()
    {
        var ofdLoadStudents = new OpenFileDialog();
        ofdLoadStudents.Multiselect = true;
        int Counter = 0;

        if (ofdLoadStudents.ShowDialog() == DialogResult.OK)
        {
            foreach (string studentList in ofdLoadStudents.FileNames)
            {
                foreach (string Students in File.ReadAllLines(studentList))
                {
                    //[Period 1]         | [ReadAllLines Data]
                    //has about 10 items | all "" fields.
                    //only loading total of 6 lines with 2 files combined.
                    listViewStudents.Items.Add(new ListViewItem(new string[] { Counter.ToString(), Students })); //This is the new code
                    Counter++;
                }
            }
        }
    }

This will lead to a listView which displays a series of numbers 0,1,2... up to the number of lines in the text file.

If you want to display the student name instead then flip around the Students and Counter.ToString() elements in the array.

listViewStudents.Items.Add(new ListViewItem(new string[] { Counter.ToString(), Students }));