1.11M Members

multiform students and scores

 
0
 

Here the error I get:
Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index


Here the main form where the error comes up:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace maint_student_scores
{
    public partial class Form1 : Form
    {
        public List<Student> studentList = new List<Student>();

        public Form1()
        {
            InitializeComponent();

            students.DataSource = studentList;  //Show students.
            students.DisplayMember = "Name";  //Display their name
        }

        public void UpdateStudentList()
        {
            students.DataSource = null;
            students.DataSource = studentList;
            students.DisplayMember = "Name";
        }

        public bool AddStudent(Student studentToAdd)
        {
            try
            {
                this.studentList.Add(studentToAdd); //add student to the list.
                UpdateStudentList(); //update student list.
            }
            catch { return false; }
            return true;
        }

        public bool UpdateStudent(int originalIndex, Student studentToEdit)
        {
            try
            {
                Student student = GetStudent(originalIndex);  //select index of student
                student.Name = studentToEdit.Name;  //name of student
                this.studentList.RemoveAt(originalIndex); //remove the student at the index selected
                this.studentList.Insert(originalIndex, student); //insert new student at index.
                UpdateStudentList(); //update student list
            }
            catch { return false; }
            return true;
        }

        public Student GetStudent(int id)  //Get student index
        {
            return studentList[id];
        }

        public bool DeleteStudent(int id) //remove student at index.
        {
            try
            {
                studentList.RemoveAt(id); 
                UpdateStudentList();
            }
            catch { return false; }
            return true;
        }

        private void updateStudent_Click_1(object sender, EventArgs e)
        {
            UpdateStudentForm updateStudentForm = new UpdateStudentForm(this, students.SelectedIndex); //pass curent info to new form
            updateStudentForm.Show(); //open new form
        }

        private void deleteStudent_Click_1(object sender, EventArgs e)
        {
            if (!DeleteStudent(students.SelectedIndex))  //check if student is selected from list.
                MessageBox.Show("Error deleting student..."); //throw message box saying that a student isn't selected.
        }

        private void ExitButton_Click_1(object sender, EventArgs e)
        {
            this.Dispose();  //clear everything
            this.Close();  //close form
        }

        private void addStudent_Click(object sender, EventArgs e)
        {
            AddStudentForm addStudentForm = new AddStudentForm(this);  //pass info to new form
            addStudentForm.Show(); // open new form
        }

        private void students_SelectedIndexChanged_1(object sender, EventArgs e)
        {
            Student student = GetStudent(students.SelectedIndex);  //select index from list
            ScoreTotalTextBox.Text = student.GetScoreTotal().ToString(); //show Score Total to box
            ScoreCountTextBox.Text = student.GetScoreCount().ToString(); //show Score Count to box
            ScoreAverageTextBox.Text = student.GetScoreAverage().ToString(); //show Score Average to box               
        }  
    }
}

Here the form that when I press ok, cause the error on the main form:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace maint_student_scores
{
    public partial class UpdateStudentForm : Form
    {
        private Form1 parentForm;  //main form
        private Student studentToEdit; //student list
        private int index; //index

        public UpdateStudentForm(Form1 parentForm, int index)  //update parent form (Form1) with the new student and scores
        {
            this.parentForm = parentForm;
            this.index = index;
            this.studentToEdit = this.parentForm.GetStudent(index);

            InitializeComponent();

            this.StudentName.Text = this.studentToEdit.Name;
            UpdateScoreDisplay();
        }

        public void AddScoreToStudent(int value) //add score to current student and display in the list
        {
            studentToEdit.AddScore(value);
            UpdateScoreDisplay();
        }

        public void UpdateScoreAtIndex(int id, int value)  //update a score selected from the list
        {
            studentToEdit.GetScores()[id] = value;
            UpdateScoreDisplay();
        }

        public int GetScoreAtIndex(int id)  //get the score index
        {
            return studentToEdit.GetScoreAt(id);
        }

        private void UpdateScoreDisplay()  //update the score display list
        {
            this.CurrentScores.DataSource = null;
            this.CurrentScores.DataSource = studentToEdit.GetScores();
        }

        private void AddScoreButton_Click(object sender, EventArgs e)  //open the add score form
        {
            AddScoreForm addScoreForm = new AddScoreForm(this);
            addScoreForm.Show();
        }

        private void RemoveScoreButton_Click_1(object sender, EventArgs e) //remove a score from current index and update display list
        {
            studentToEdit.GetScores().RemoveAt(CurrentScores.SelectedIndex);
            UpdateScoreDisplay();
        }

        private void ClearScoresButton_Click_1(object sender, EventArgs e) //clear all scores
        {
            studentToEdit.DestroyScores();
            UpdateScoreDisplay();
        }

        private void CloseButton_Click_1(object sender, EventArgs e)
        {
            this.Close();  //close form
        }

        private void UpdateButton_Click_1(object sender, EventArgs e)  //open update form for current student
        {
            Student updatedStudent = new Student();
            updatedStudent.Name = StudentName.Text;
            this.parentForm.UpdateStudent(index, updatedStudent);
            this.Close();
        }

        private void UpdateScoresButton_Click(object sender, EventArgs e)
        {
            UpdateScoreForm updateScoreForm = new UpdateScoreForm(this, CurrentScores.SelectedIndex);
            updateScoreForm.Show();
        }
    }
}

Let me know if you need anything else, I'll keep playing with it and see if I can find something.

And out of curiosity of learning, where would you use code like this: return (Student)studentList.ElementAt(id); ?

 
0
 

I need you to post your zipped up project--current version...

 
0
 

Ok thank you for the help. Let me know if something doesn't make sense. i'm still commenting\changing a few things to be a textbox (if there are any left).

Thank you again.

Attachments code.zip (83.88KB)
 
0
 

I need to get you to a good starting point. Begin by making these changes. Do not remove the comments at this time because I want you to be able to look back and reflect at what we did:

public partial class UpdateStudentForm : Form
    {
        // You don't need to know about the parent form!!!
        //private Form1 parentForm;  //main form
        
        private Student studentToEdit; //student list
        
        // there is no need to carry around this index, which can cause you index out of range too.
        //private int index; //index

        // this form only needs to know about this student to udpate...
        public UpdateStudentForm(Student updateStudent)
        {
            // set this form's student reference to one passed in...
            this.studentToEdit = updateStudent;

            InitializeComponent();

            // OK--setting textbox for name and listbox for scores...
            this.StudentName.Text = this.studentToEdit.Name;
            UpdateScoreDisplay();
        }

And in main Form1,...

private void updateStudent_Click_1(object sender, EventArgs e)
        {
            // Get the index of the currently selected student in the ListBox
            // Remember naming conventions: students s/b something 
            // like: lbxStudents or listBoxStudents or lbStudents etc...
            int index = students.SelectedIndex;
            
            // ensure this index is valid and in range with our list...
            System.Diagnostics.Debug.Assert(index >= 0 && index < studentList.Count);

            // Get a reference to the selected student in the studentList...
            Student updateStudent = studentList[index];

            // Pass in only the student we are updating...
            UpdateStudentForm updateStudentForm = new UpdateStudentForm(updateStudent);

            // Create form and show as modeless! (ShowDialog())
            updateStudentForm.ShowDialog(); //open new form
        }

EDIT: Let me know when you have those changes and can compile and run (can add student with scores and bring up student in update form).

 
0
 

I need to get you to a good starting point. Begin by making these changes. Do not remove the comments at this time because I want you to be able to look back and reflect at what we did:

public partial class UpdateStudentForm : Form
    {
        // You don't need to know about the parent form!!!
        //private Form1 parentForm;  //main form
        
        private Student studentToEdit; //student list
        
        // there is no need to carry around this index, which can cause you index out of range too.
        //private int index; //index

        // this form only needs to know about this student to udpate...
        public UpdateStudentForm(Student updateStudent)
        {
            // set this form's student reference to one passed in...
            this.studentToEdit = updateStudent;

            InitializeComponent();

            // OK--setting textbox for name and listbox for scores...
            this.StudentName.Text = this.studentToEdit.Name;
            UpdateScoreDisplay();
        }

And in main Form1,...

private void updateStudent_Click_1(object sender, EventArgs e)
        {
            // Get the index of the currently selected student in the ListBox
            // Remember naming conventions: students s/b something 
            // like: lbxStudents or listBoxStudents or lbStudents etc...
            int index = students.SelectedIndex;
            
            // ensure this index is valid and in range with our list...
            System.Diagnostics.Debug.Assert(index >= 0 && index < studentList.Count);

            // Get a reference to the selected student in the studentList...
            Student updateStudent = studentList[index];

            // Pass in only the student we are updating...
            UpdateStudentForm updateStudentForm = new UpdateStudentForm(updateStudent);

            // Create form and show as modeless! (ShowDialog())
            updateStudentForm.ShowDialog(); //open new form
        }

EDIT: Let me know when you have those changes and can compile and run (can add student with scores and bring up student in update form).

I can compile run and everything, just can't add more than one student :S, give me an error at: return studentList[id];

 
0
 

I'm glad if you understand--very good. Before you get side-tracked, Here are some more changes I want you to make, then you can disappear for a while (LOL) while you produce the remaining implementation...

public partial class UpdateScoreForm : Form
    {
        // no need to know about the other form...
        //private UpdateStudentForm parentForm; //current form

        // Score list and index to score being edited
        private int index; //index of score
        private List<int> Scores;

        // Pass in Score list and index to score being edited...
        // The reason we don't just pass in the single score, is because simple
        // types are passed in by value and the result would be lost...
        // There are other ways we could have done this, but let's keep it simple for now...
        public UpdateScoreForm(int index, List<int> Scores)//UpdateStudentForm parentForm, int index)  //pull score from previous form.
        {
            //this.parentForm = parentForm;

            // this.Scores is a reference to Scores passed in, so when we update it,
            // the change will appear in the caller's list too...
            this.index = index;
            this.Scores = Scores;

            InitializeComponent();

            //this.CurrentScore.Text = this.parentForm.GetScoreAtIndex(index).ToString();

            // Set textbox (naming conventions!) to correct score value...
            this.CurrentScore.Text = Scores[index].ToString();
        }

Then in calling form:

private void UpdateScoresButton_Click(object sender, EventArgs e)
        {
            // get the index of selected listbox item (score)...
            // Again, use naming conventions for a listbox...
            int index = CurrentScores.SelectedIndex;
            
            // ensure there is a score selected, or there is nothing to update...
            System.Diagnostics.Debug.Assert (index >= 0);
            
            List<int> scores = studentToEdit.GetScores();

            // ensure the index is within range of our scores list...
            System.Diagnostics.Debug.Assert(index < scores.Count);

            // call the update score form...
            // only information it needs is this score...
            // passing in scores list because needs reference (see comments at constructor)...
            UpdateScoreForm updateScoreForm = new UpdateScoreForm(index, scores);

            // Create form and show modeless! (ShowDialog())...
            updateScoreForm.ShowDialog();
        }

Which will break this, so comment out code until you can fix it to work with the Scores list:

private void UpdateButton_Click_1(object sender, EventArgs e) //update current score that was selected from previous form
        {
            // TODO: update the Scores list with the change the user typed...

            //this.parentForm.UpdateScoreAtIndex(index, Convert.ToInt32(CurrentScore.Text));
            this.Close();
        }

If you understand those changes, you should be good to go. Put some time into it and I think you will be alright. Remember naming conventions and leave in those comments I put in until you finish this bad boy!

Cheers!

 
0
 

lol, will do. I'm step out real quick (issue w\ work atm ~_~), but you should hear from in about 20-30min if I blow this project up again lol. Thanks for the help, the changes look to make sense so far.

 
0
 
private void UpdateButton_Click_1(object sender, EventArgs e) //update current score that was selected from previous form
        {
            // TODO: update the Scores list with the change the user typed...
 
            //this.parentForm.UpdateScoreAtIndex(index, Convert.ToInt32(CurrentScore.Text));
            this.Close();
        }

This is the only part that is killing me at the moment is trying to get the string to update back to the previous form. I know its staring me at the face and that some how I have to convert it to an int32 and throw it back as a ToString to show up on the CurrentScores List.

 
0
 

Reverse engineer the problem... I have shown you how to get the information into the form and you have a reference to the student's Scores and an index of the score being edited. Look how the constructor pulled the student's score, then just reverse that process to put the update in there.

If you are going to be a programmer, or claim to have learned these skills, you need to pick up these fundamentals and begin thinking in a logical manner to figure things like this out.

I really don't know what else to do if you cannot figure this out; other than to write you application for you, but I'm not going to do that and I hope that is not what you want.

 
0
 

Reverse engineer the problem... I have shown you how to get the information into the form and you have a reference to the student's Scores and an index of the score being edited. Look how the constructor pulled the student's score, then just reverse that process to put the update in there.

If you are going to be a programmer, or claim to have learned these skills, you need to pick up these fundamentals and begin thinking in a logical manner to figure things like this out.

I really don't know what else to do if you cannot figure this out; other than to write you application for you, but I'm not going to do that and I hope that is not what you want.

Thank you for that tip, I looked at it really hard and its clicking.

So far:

Scores[index] = Convert.ToInt32(CurrentScore.Text);
            Scores[index].ToString();
            this.Close();

I know I'm on the right track now; just have to figure out how to update the parentform after the close. And I think my light bulb just went off.

EDIT: still trying to figure out how to get the previous form to update the score in the list. I can get the score to update and then when I select the same one it comes up with the new value I selected.

And on a side note, I really hope I never have to work full time as a programmer :S, I kinda got stuck into doing C#\C++ due to it being apart of my Computer Science degree and they didn't have the classes I really wanted (linux shell scripting) and stuff like that I have done in the past and use daily. But... You guys have been a HUGE help in getting me through this and making me not quit so props for that.

 
0
 

WOW... So I decided to take a look around at my code and started playing with things. Just a real quick question: is there a limit amount of memory or char or value that a List can hold before it might throw some errors about an index being out of range and stuff, if so I know what I'm doing wrong and this is going to be a lot easier for me to figure out.
Thank you.

 
0
 

I can assure you that the index out of range, based on the code I saw, was/is not being caused by lack of memory.

EDIT: You know that when you are debugging this you can look at the list Count property and the value of the index where the error is thrown. You will see the index is >= to Count, or is less than 0, all of which indicate an improper index out of range.

 
0
 

yeah just kinda remembered that when I was messing around with the debug. Yeah I believe I'm just about done with this, fixing a couple minor things with the index on the other forms, but things are slowly working they're way into place. I just hope that trying to write all the data to a file on a local machine and pulling it back up from a location of that file is easier than doing this whole thing :(.

 
0
 

I think my final two questions I have would be:
1) My delete button throw me my error about out of range index.

public Student GetStudent(int id)  //Get student index
        {
            return studentList[id];
        }

        public bool DeleteStudent(int id) //remove student at index.
        {
            try
            {
                studentList.RemoveAt(id); 
                UpdateStudentList();
            }
            catch { return false; }
            return true;
        }

private void deleteStudent_Click_1(object sender, EventArgs e)
        {
            if (!DeleteStudent(studentsList.SelectedIndex))  //check if student is selected from list.
                MessageBox.Show("Error deleting student..."); //throw message box saying that a student isn't selected.
        }

I'm not sure why it would throw out a debug error, because it does exactely what the code says, remove student at (id) which is the index.

And the final one is, if there are no scores for a student how would I make it show just 0 for the 3 boxes on the main form, because I get an error with

public int GetScoreAverage()
        {
            return GetScoreTotal() / GetScoreCount();
        }

I know in the past I worked with a float value and had all the calculation done on one single form. Would it work the sameway?

 
0
 
private void deleteStudent_Click_1(object sender, EventArgs e)
        {
            if (!DeleteStudent(studentsList.SelectedIndex))  //check if student is selected from list.
                MessageBox.Show("Error deleting student..."); //throw message box saying that a student isn't selected.
        }

Why did you change this method? It was more correct the way you had it before. This won't even compile because "studentList" does not have a SelectedIndex property.

 
0
 

Why did you change this method? It was more correct the way you had it before. This won't even compile because "studentList" does not have a SelectedIndex property.

I never changed this method. Unless I really just screwed everything up and removed the newer copy of my code and replaced it with my old code. Do you happen by chance to have the code I put there before? I think I just screwed my whole work space again ~_~.

EDIT: Yup... Just lost some of my work... That delete part got changed I guess when I was copying\pasting some code around and I didn't save it.

 
0
 

Here is what you had before:

private void deleteStudent_Click_1(object sender, EventArgs e)
        {
            if (!DeleteStudent(students.SelectedIndex))  //check if student is selected from list.
                MessageBox.Show("Error deleting student..."); //throw message box saying that a student isn't selected.
        }
 
0
 

ok yeah I do remember changing that then just was testing something, but still throw the index out of wack when I try to remove a student from the list and not having much luck figuring out why.

 
0
 

You need to check that index because maybe there is no student selected or something.

if (students.SelectedItem < 0)
    MessageBox.Show("No student selected...");
else if (students.SelectedItem >= studentList.Count)
    MessageBox.Show("Programmer Error: List out of Sync with ListBox!");

I have dinner plans so I have to leave now... Good luck and look at all of those comments I made for you showing how to check index to make sure it is valid...

Question Answered as of 4 Years Ago by DdoubleD and Ryshad
You
This question has already been solved: Start a new discussion instead
Post:
Start New Discussion
Tags Related to this Article