Hi all,

I'm trying to access a list in a class made in another class and display it in a listbox but its not working. I most probably have to make a small change to be able to get it to work. So please check in the code if you can see where the problem is.

I have two classes - Race and Runner.

The Race class

Where I created the list and added the runners into it using a method that I call in the main form.

namespace HW2
{
    class Race
    {
        public List<Runner> myList = new List<Runner>();

        private double mDistance;
        private string mName;
        private string mDate;
        private string mRunnerList;

        public double Distance
        {
            get { return mDistance; }
            set { mDistance = value; }
        }

        public string Name
        {
            get { return mName; }
            set { mName = value; }
        }

        public string Date
        {
            get { return mDate; }
            set { mDate = value; }
        }

        public string RunnerList
        {
            get { return mRunnerList; }
            set { mRunnerList = value; }
        }

        public void AddRunnerInfo(string name, int number)
        {
            Runner runA = new Runner();

            runA.Name = name;

            foreach (Runner run in myList)
            {
                for (int i = 0; i < myList.Count; i++)
                {
                    runA.RaceNumber = (number + i);
                }
            }

            myList.Add(runA);

            //TESTING THE RACENUMBER ASSIGNMENT
            MessageBox.Show(Convert.ToString(runA.Name));
            MessageBox.Show(Convert.ToString(runA.RaceNumber));
        }
    }
}

The Runner Class

Where I wish to display the added items in the list in the Display() method

namespace HW2
{
    class Runner
    {
        public string mName;
        public int mPosition;
        public int mRaceNumber;
        public double mTime;

        public string Name
        {
            get { return mName; }
            set { mName = value; }
        }

        public int Position
        {
            get { return mPosition; }
            set { mPosition = value; }
        }

        public int RaceNumber
        {
            get { return mRaceNumber; }
            set { mRaceNumber = value; }
        }

        public double Time
        {
            get { return mTime; }
            set { mTime = value; }
        }

        public Runner()
        {
            mName = "No Name";
            mPosition = 0;
            mRaceNumber = 0;
            mTime = 0.0;
        }

        public void Display(Form1 f1)
        {
            Race r = new Race();
            f1.listBox1.Items.Clear();

            foreach (Runner runner in r.myList)
            {
                for (int i = 0; i < r.myList.Count; i++)
                {
                    f1.listBox1.Items.Add(runner.Name + ", " + runner.Position + ", " + runner.RaceNumber + ", " + runner.Time + "\n");
                    i++;
                }
                MessageBox.Show(runner.mName);
            }
        }
    }
}

My main Form

Where I call the methods to what they're supposed to do :)

private void button4_Click(object sender, EventArgs e)
        {
            //Adding a new runner to the race by using the AddRunnerInfo() method
            string name;
            int number = 1;

            //NAME
            name = textBox4.Text;
            myRunner.Name = name;
            //RACENUMBER
            myRunner.RaceNumber = number;

            //ADD PARAMETERS TO THE METHOD
            myRace.AddRunnerInfo(name, number);
            //DISPLAY THE RUNNER'S DETAILS
            myRunner.Display(this);
        }

I am very close but cant seem to find the problem

ANY help will be much appreciated! :)

Joe

Hi

Not sure how you are adding data to your classes but looking at your code I can see you have a lot of Windows Forms code within your classes. This is a bad design. Your classes should not need to know anything about Windows Forms. It shouldn't even need to know about a ListBox. Instead, your class should return data which you then consume in your form. For example, I modified your Display routine to the following:

    public List<Runner> GetRunners()
    {
        Race r = new Race();
        List<Runner> returnValue = new List<Runner>();

        foreach (Runner runner in r.myList)
        {
            for (int i = 0; i < r.myList.Count; i++)
            {
                returnValue.Add(new Runner { Name = runner.Name, Position = runner.Position, RaceNumber = runner.RaceNumber, Time = runner.Time });
                i++;
            }                
        }
        return returnValue;
    }

Which will loop through your Race list and build a new list of Runner which is then returned. Then when you want to display this in the ListBox you would do something like this in your Form code:

//DISPLAY THE RUNNER'S DETAILS
foreach (var runner in myRunner.GetRunners())
{
    listBox1.Items.Add(runner.Name + ", " + runner.Position + ", " + runner.RaceNumber + ", " + runner.Time + "\n");
}

I couldn't test this as I have no data. Hopefully it will point you in the right direction though.

HTH

Hmmm, I tested it and it still does not want to display in the listBox (As it was) :(

In the race class it successfully adds new runners to the list. I know this works but for some reason I cant get that data to display in the listBox.

Yes, you are adding to your list (I was able to test by adding some dummy data), but you are also declaring a new instance of the Race class in your Display routine (and hence in my GetRunners function which I hadn't spotted originally), so the myList will be empty.

Thinking about this, shouldn't the Race be responsible for returning the list of runners, not the Runner class, after all a Race has many Runners.

I moved the GetRunners method to the Race class and removed the instantiation of the Race class from the method:

        public List<Runner> GetRunners()
        {
            List<Runner> returnValue = new List<Runner>();

            foreach (Runner runner in myList)
            {
                for (int i = 0; i < myList.Count; i++)
                {
                    returnValue.Add(new Runner { Name = runner.Name, Position = runner.Position, RaceNumber = runner.RaceNumber, Time = runner.Time });
                    i++;
                }
            }
            return returnValue;
        }

Now when you call it from your form it does return data to the ListBox using:

            //DISPLAY THE RUNNER'S DETAILS
            foreach (var runner in myRace.GetRunners())
            {
                listBox1.Items.Add(runner.Name + ", " + runner.Position + ", " + runner.RaceNumber + ", " + runner.Time + "\n");
            }

HTH

Aaaah I see! That worked! :D This is a form of encapsulation right?

Yes, in some ways it is. The basic principle is that your classes should be created to do or describe a specific thing. They should not need to know anything about their outside environment. So your Runner class should only be interested in describing a Runner. Name, Time etc. Your Race class should only be concerned about the Race and who is running in it. There is a link between the two that is natural, you can't have a Race without Runners right.

Your form on the other hand does not need to know internal workings of either of these classes, it just needs to know that it can set a Name property or add a Runner to the Race and that it can get a list of runners back which it can then use to update it's own UI.

This article has been dead for over six months. Start a new discussion instead.