c# list.add() overwrite the object at position 0 - c#

i am updating my question to this
i created new class Student
class Student
{
private string _firstName;
private string _lastName;
private int _exam1;
private int _exam2;
private int _exam3;
private int _finalExam;
// First Name Property
public string FirstName
{
get { return _firstName; }
set { _firstName = value; }
}
//Last Name Property
public string LastName
{
get { return _lastName; }
set { _lastName = value; }
}
//Exam 1 Property
public int Exam1
{
get { return _exam1; }
set { _exam1 = value; }
}
// Exam 2 Property
public int Exam2
{
get { return _exam2; }
set { _exam2 = value; }
}
//Exam 3 Property
public int Exam3
{
get { return _exam3; }
set { _exam3 = value; }
}
//Final Exam Property
public int FinalExam
{
get { return _finalExam; }
set { _finalExam = value; }
}
}
}
this is my add new student form class with one method to add new student
public class AddStudent : Form
{
StudentForm stu = null;
public AddStudent()
{
InitializeComponent();
stu = new StudentForm();
stu.Show();
}
private void btnSubmit_Click(object sender, EventArgs e)
{
// split the name into first and last name
string[] name = txtName.Text.Split(',');
Student std = new Student();
std.FirstName = name[0];
std.LastName = name[1];
std.Exam1 = Int32.Parse(txtExam1.Text);
std.Exam2 = Int32.Parse(txtExam2.Text);
std.Exam3 = Int32.Parse(txtExam3.Text);
std.FinalExam = Int32.Parse(txtFinal.Text);
stu.addItem(std);
this.Hide();
}
}
}
and this is my main form it has listbox to display list of students
public class StudentForm : Form
{
public StudentForm()
{
InitializeComponent();
}
public List<Student> students = new List<Student>();
public void addItem(Student std)
{
students.Add(std);
// it always show me 1 item in list
MessageBox.Show(students.Count.ToString());
}
}

Here's how your code is progressing, with comments added and irrelevant code removed:
private void btnSubmit_Click(object sender, EventArgs e)
{
...
// create a _new_ Student form
Student std = new Student();
...
// Add the student form to itself (huh?)
std.addItem(std);
// hide this form
this.Hide();
// show the new form
std.Show();
}
So you are always showing a new form with one item - the one that was just created.

Yeah that's cause in your btnSubmit_Click every time you are creating a new instance of the form Student and calling the addItem() method.
You rather move this field to a separate class like
public class Data
{
private string _firstName;
private string _lastName;
private int _exam1;
private int _exam2;
private int _exam3;
private int _finalExam;
}
have the form instance created in the start up like
public partial class AddStudent : Form
{
Student stu = null;
public AddStudent()
{
InitializeComponent();
stu = new Student();
stu.Show();
}
Change the list in Form1
public List<Data> students = new List<Data>();
In button click just add the Data instance like
private void btnSubmit_Click(object sender, EventArgs e)
{
// split the name into first and last name
string[] name = txtName.Text.Split(',');
Data std = new Data();
std.FirstName = name[0];
std.LastName = name[1];
std.Exam1 = Int32.Parse(txtExam1.Text);
std.Exam2= Int32.Parse(txtExam2.Text);
std.Exam3 = Int32.Parse(txtExam3.Text);
std.FinalExam = Int32.Parse(txtFinal.Text);
stu.addItem(std);
this.Hide();
}

This is because you're creating the Student form each time using this line:
Student std = new Student();
So every time you're clicking submit, you're creating a new Student form which creates a new empty public List<Student>
You need to seperate your model (Student) from your UI (StudentForm) and (AddStudentForm):
public class Student
{
public string FirstName { set; get; }
private string LastName { set; get; }
private int Exam1 { set; get; }
private int Exam2 { set; get; }
private int Exam3 { set; get; }
private int FinalExam { set; get; }
}
You don't need to create a new StudentForm each time you add a Student. Instead, you can have one StudentForm and use ShowDialog() when navigating to the Addition Screen, this you go back to the same instance of StudentForm.

Try removing the Class Student instantiation out of the event - btnSubmit_Click event
Student std = new Student();

Related

C# Sending user input from one form to another without the second form opening

I'm currently trying to send customer names from one listbox in form1 to another listbox in a separate form (form2). I want to do this by when the user clicks the add button the customer name it will automatically send it to the other form without the second form opening. Is this possible?
Also currently if I exit from form1 and go back into it without closing the program all the input in the listbox is lost, is it possible to save the input in there some how?
Form 1:
public partial class Form1 : Form
{
// Creates a controller object
Controller control = new Controller();
public Form1()
{
InitializeComponent();
DisplayCustomers();
// FormAccounts formA = new FormAccounts(listBoxCustomer);
}
// Add Customer
// Completed
private void buttonAddCustomer_Click(object sender, EventArgs e)
{
Customer c = new Customer();
c.firstName = textBox1.Text;
control.Add(c);
// control.list.Add(c);
listBoxCustomer.Items.Add(c.firstName);
}
// Displays Customers to list box
public void DisplayCustomers()
{
listBoxCustomer.Items.Clear();
foreach(Customer c in control.list)
{
listBoxCustomer.Items.Add(c.FirstName);
}
}
}
}
Form 2:
public partial class Form2 : Form
{
Controller control = new Controller();
public FormAccounts()
{
InitializeComponent();
DisplayCustomers();
}
// Displays Customers to list box
public void DisplayCustomers()
{
listBoxCustomerName.Items.Clear();
foreach (Customer c in control.list)
{
listBoxCustomerName.Items.Add(c.FirstName);
}
}
}
Controller class:
class Controller
{
public List<Customer> list = new List<Customer>();
// Method to create customer object
public void CreateCustomer(string firstName)
{
list.Add(new Customer(firstName));
}
// Add Customer
public void Add(Customer c)
{
list.Add(c);
}
}
Customer class:
class Customer
{
private List<Account> customerAccounts;
private static int nextID = 1;
public int customerId;
public string firstName;
public int CustomerId { get => customerId; set => customerId = value; }
public string FirstName { get => firstName; set => firstName = value; }
public Customer()
{
CustomerId = nextID;
nextID++;
}
public Customer(string newFirstName) : this()
{
FirstName = newFirstName;
}

DisplayMembers in ListBox - Not displaying anything

In Form1, why isn't myListBox displaying my name property inside of class Student
Form1
private static List<Student> studentListHome = new List<Student>();
...
public void BindData()
{
if (studentListHome != null)
{
studentListBox.DataSource = studentListHome;
studentListBox.DisplayMember = "name";
}
}
private void refreshButton_Click(object sender, EventArgs e)
{
BindData();
}
Student
private string name;
public string Name
{
get
{
return name;
}
}
...
public Student(string _name, int _id, string _bday)
{
name = _name;
id = _id;
bday = _bday;
}
Because 'name' is a private string.
Try using 'Name' which is your property.
studentListBox.DisplayMember = "Name";
This fixed it
Changing
studentListBox.DisplayMember = "Name";
To
foreach(Student s in studentListHome){
studentListBox.DisplayMember = "Name";
}

How to pass a string from Class 1 to Class 2 to Class 3?

I have 3 classes (UCourse, Student and Teacher) and each class has a unique string property.
Is there a simple way I can take the string property from the first class UCourse, pass it into a 2nd class Student, and then pass that string plus another string from the 2nd class into a 3rd class Teacher?
This is what I have so far for my 3 classes:
using System;
namespace EDXonline_AssignmentFour
{
class Program
{
class UCourse
{
// Set the unique string for the 1st class
private string course = "Computer Scienece";
public string Course
{
get { return course; }
}
}
class Student
{
// Get the string from the 1st class
UCourse ucourse = new UCourse();
public string coursef1
{
get { return ucourse.Course; }
}
// Set the unique string for the 2nd class
private string name = "zach";
public string Name
{
get { return name; }
}
}
class Teacher
{
Student student = new Student();
private string namet = "Sally";
// Get the unique string from the 2nd class
public string namef1
{
get { return student.Name; }
}
// Set the unique string for the 3rd class
public string Namet
{
get { return namet; }
}
}
}
}
Then, I need to create an instance of Teacher and by using only this instance of Teacher, I need to output all string properties from each of the 3 classes like this:
public static void Main (string [] args)
{
Teacher teacher = new Teacher();
Console.WriteLine("{0} and {1} are in {2}",
teacher.namef1, teacher.Namet /*, UCourse string from the 1st class goes here*/);
}
So far that works to display the strings from the 2nd and 3rd classes, but how can I get the value of the UCourse string from the first class as well?
If you want to use your existing code and keep passing the strings through properties, then you almost solved it because your Main() method already shows the correct values of the strings from the 2nd and 3rd classes.
To access the string from the 1st class and use it in the 3rd class, you can add another property to the 3rd class to get it (same as you already did to get the string from the 2nd class).
For example:
class Teacher
{
Student student = new Student();
// Get the unique string from the 2nd class
public string namef1
{
get { return student.Name; }
}
// Get the unique string from the 1st class that's already stored in the 2nd class
public string UCourseName
{
get { return student.coursef1; }
}
// Set the string for the third class
private string namet = "Sally";
public string Namet
{
get { return namet; }
}
}
And then you can update your Main() method to use it like this:
public static void Main(string[] args)
{
Teacher teacher = new Teacher();
// Writes "Zach and Sally are in Computer Science"
Console.WriteLine("{0} and {1} are in {2}",
teacher.namef1, teacher.Namet, teacher.UCourseName);
Console.ReadLine();
}
that would be :
internal class Program
{
private static void Main( string[] args )
{
Teacher teacher = new Teacher();
Console.WriteLine("{0} and {1} are in {2}",
teacher.Namef1, teacher.Namet, teacher.Course);
}
private class UCourse
{
// Set the unique string for the 1st class
private readonly string course = "Computer Scienece";
public string Course { get { return this.course; } }
}
private class Student
{
// Set the unique string for the 2nd class
private readonly string _name = "zach";
public string Name { get { return this._name; } }
// Get the string from the 1st class
private readonly UCourse _ucourse = new UCourse( );
public string Coursef1 { get { return this._ucourse.Course; } }
}
private class Teacher
{
private readonly Student _student = new Student( );
// Get the unique string from the 1nd class
public string Course { get { return this._student.Coursef1; } }
// Get the unique string from the 2nd class
public string Namef1 { get { return this._student.Name; } }
// Set the unique string for the 3rd class
private readonly string _namet = "Sally";
public string Namet { get { return this._namet; } }
}
}
I recommend that you rethink your classes. Here is a small example:
using System;
using System.Collections.Generic;
namespace Example
{
public class Course
{
public string CourseTitle { get; set; }
public List<Student> Students { get; set; }
public Course(string courseTitle)
{
CourseTitle = courseTitle;
Students = new List<Student>();
}
}
public class Student
{
public string Name { get; set; }
public Student(string name)
{
Name = name;
}
}
public class Teacher
{
public string Name { get; set; }
public List<Course> Courses { get; set; }
public Teacher(string name)
{
Name = name;
Courses = new List<Course>();
}
}
class Program
{
static void Main(string[] args)
{
List<Teacher> teachers = new List<Teacher>();
Course course1 = new Course("Astrophysics A");
Course course2 = new Course("Coding C#");
Student student1 = new Student("Peter");
Student student2 = new Student("Bill");
Student student3 = new Student("Anna");
Teacher teacher1 = new Teacher("Mr. Williams");
Teacher teacher2 = new Teacher("Mr. Jacobson");
course1.Students.Add(student1);
course1.Students.Add(student3);
course2.Students.Add(student2);
teacher1.Courses.Add(course1);
teacher2.Courses.Add(course2);
teachers.Add(teacher1);
teachers.Add(teacher2);
foreach (Teacher teacher in teachers)
{
foreach (Course course in teacher.Courses)
{
foreach (Student student in course.Students)
{
Console.WriteLine("{0} and {1} are in {2}", student.Name, teacher.Name, course.CourseTitle);
}
}
}
Console.ReadLine();
}
}
}
I guess this way provides you more flexibility, in your code only 1 to 1 connections are possible.
Hope this was helpful.

C# Communication between parent form and child form

My project has two classes. The first class has information about continents and it contains also a list of objects of countries (another class).
I also declared a list of continents that contains all the continents.
I've succeeded in filling the list from a file, and succeeded to show them in a DataGridView in the same form. But the problem is that I didn't find a way to show them in a child form that contains a DataGridView.
So, how can I transfer the list of continents to the child form so that I can be able to show them in it?
I tried serialiization and deserialization, but it didn't work, I just see the name of members of continent class and nothing else.
Here are the two class and code of toolstrip that show the child form:
// first class of continent
namespace WindowsFormsApplication1
{
[Serializable]
class continent
{
//champs
private string nomc;
public string Nomc
{
get { return this.nomc; }
}
private string sup;//SUP
public string Superficie
{
get { return this.sup; }
set { this.sup = value; }
}
private string pop;//POP
public string Population
{
get { return this.pop; }
set { this.pop = value; }
}
private string dens;//DENS :
public string Densité
{
get { return this.dens; }
set { this.dens = value; }
}
private string nbp;//NBP : 54 :
public string nombre_de_Pays
{
get { return this.nbp; }
set { this.nbp = value; }
}
private string fus;//FUS )
public string Fuseaux_horaires
{
get { return this.fus; }
set { this.fus = value; }
}
private string pnb;//PNB
public string PNB_habitant
{
get { return this.pnb; }
set { this.pnb = value; }
}
//constructeur
public continent(string nom)
{
this.nomc = nom;
}
public continent()
{
// TODO: Complete member initialization
}
//list of countries of that continent
public List<country> listep = new List<country>();
}
// class of countries
namespace WindowsFormsApplication1
{
[Serializable]
class country
{
//champs
private string nom_p;
public string Nom_pays
{
get { return this.nom_p; }
set { this.nom_p = value; }
}
private string cap;//PCAP
public string Capitale
{
get { return this.cap; }
set { this.cap = value; }
}
private string sup;// PSUP
public string Superficie
{
get { return this.sup; }
set { this.sup = value; }
}
private string reg;// REG
public string Régime_politique
{
get { return this.reg; }
set { this.reg = value; }
}
private string dev;//PDEV nationale
public string Devise
{
get { return this.dev; }
set { this.dev = value; }
}
private string hym;// PHYM
public string Hymne
{
get { return this.hym; }
set { this.hym = value; }
}
private string lg;// PLG
public string Langue
{
get { return this.lg; }
set { this.lg = value; }
}
private string mo;// PMO
public string Monnaie
{
get { return this.mo; }
set { this.mo = value; }
}
private string de;
public string PDE
{
get { return this.de; }
set { this.de = value; }
}
//constructeur
public country (string nom)
{
this.nom_p = nom;
}
}
}
and the code in the form is
//liste of contnents
List<continent> listec = new List<continent>();
// i filled it from a file
//here the code of toolstrip that open the childform
private void listeContinentToolStripMenuItem_Click(object sender, EventArgs e)
{
listecont flc = new listecont();
flc.ShowDialog();
flc.MdiParent = this;
}
In your child form, add an overload to the Form constructor that takes a Form as an argument. Then when you create your child form, you can pass in an instance of your current (parent) form like, listecont flc = new listecont(this); where this is a reference of your parent form. Now your child form can make calls to parentForm.Textbox.Text = "blablabal" or what ever object you want to interact with.
Why not just add a constructor to the listecont class that takes a List<continent>? Then, the child form will have the data when it's constructed.
in your MDI child add a method:
public void SetContinentData(List<continent> list)
{
// add your DataSource to the grid
// f.e.:
dataGridView.DataSource = list;
}
and in your Toolstrip handler:
private void listeContinentToolStripMenuItem_Click(object sender, EventArgs e)
{
listecont flc = new listecont();
flc.SetContinentData(listec);
flc.ShowDialog();
flc.MdiParent = this;
}

C# List access object and add name to list

I'm trying to get all the names in a list and display them in a listbox. Here's my code.
namespace UniRecords
public partial class MainWindow
{
private University uni = new University(); //Creates a new University object
public MainWindow()
{
InitializeComponent();
}
private void btnadd_Click(object sender, RoutedEventArgs e)
{
Student newStudent = new Student(txtname.Text, txtaddress.Text, txtmatric.Text,txtcourse.Text); //Calls the student constructor to construct a student object
uni.ownsStudent(newStudent); //Calls the newStudent method in the University class
}
private void btnshow_Click(object sender, RoutedEventArgs e)
{
uni.showStudents(); //calls the showStudents method
}
private void btnlist_Click(object sender, RoutedEventArgs e)
{
}
}
}
My University class:
namespace UniRecords
class University
{
//Creates a list of students that University owns
private List<Student> owns = new List<Student>();
public University()
{
}
public void ownsStudent(Student newStudent)
{
owns.Add(newStudent);//Adds a new student to the list
}
public void showStudents()
{
foreach (Student s in owns)
{
System.Windows.MessageBox.Show(s.printDetails()); //Prints out details of each student individually
}
}
public void getStudents()
{
foreach (Student s in owns)
{
}
}
}
}
Student class:
namespace UniRecords
class Student
{
private string name;
private string dob; //Date of birth
private string course;
private string matric;
private string address;
//Constructor
public Student(string myname, string myaddress, string mymatric, string mycourse)
{
Name = myname;
Address = myaddress;
Matric = mymatric;
Course = mycourse;
}
//Uses get and set to make sure that the variables are kept private
public string Name
{
get { return name; }
set { name = value; }
}
public string Dob
{
get { return dob; }
set { dob = value; }
}
public string Course
{
get { return course; }
set { course = value; }
}
public string Matric
{
get { return matric; }
set { matric = value; }
}
public string Address
{
get { return address; }
set { address = value; }
}
public string printDetails()
{
return "student is called " + Name + " " + Address + " " + Matric + " " + Course;
}
public void listNames()
{
}
}
}
I'm trying to have btnlst_click be pressed and get output a list of all the names that have been inputted.
I know I need to use something like: foreach (Student s in owns) but I don't have permissions to do it from the mainwindow class and I'm not sure how I could pass it from the University class to mainwindow to be put in the string. Can someone offer advice?
You have to define your method to have it return a list of studentnames.
public List<string> GetStudents(){
return owns.Select(x => x.Name).ToList();
}
This roughly translates to
public List<string> GetStudents(){
var result = new List<String>();
foreach(var student in owns) {
result.add(student.Name);
}
return result;
}
This small LINQ expression will select all the names of the students and return it for you to use. Notice the List<string> return statement instead of void.
And in your main form class:
myListBox.DataSource = someUniversity.GetStudents():
I'm not familiar with GUI development in C#, so this assignment might look different.
Keep naming conventions in mind: methods are CamelCased!

Categories