I'm not completely sure the title was good for this. I'm stuck on an assignment for school there is suppose to be a video to shows how to do this but for the life of me I can't figure out how to download the student files from the pearson website. The following is the problem I'm working on.
Employee and ProductionWorker Classes
Create an Employee class that has properties for the following data:
Employee name
Employee number
Next, create a class named ProductionWorker that is derived from the Employee class. The ProudctionWorker class should have properties to hold the following data:
Shift number (an integer, such as 1, 2, or 3)
Hourly pay rate
The workday is divided into two shifts: day and night. The Shift property will hold an integer value representing the shift that the employee works. The day shift is shift 1 and the night shift is shift 2.
Create an application that creates an object of the ProductionWorker class and lets the user enter data for each of the object's properties. Retrieve the object's properties and display their values.
Here is the code I working on for it:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace classes
{
public partial class frmMainClasses : Form
{
string EmpShift = "";
string EmployeeName = "";
int EmployeeNumber = 0;
float HourlyPayRate = 0;
public class Employee
{
public string EmployeeName { get; set; }
public int EmployeeNumber { get; set; }
}
public class ProductionWorker : Employee
{
public float HourlyPayRate { get; set; }
public Shift Shift { get; set; }
}
public enum Shift
{
Day = 1,
Night = 2
}
public frmMainClasses()
{
InitializeComponent();
}
private void btxExit_Click(object sender, EventArgs e)
{
this.Close();
}
private void btnGetInfo_Click(object sender, EventArgs e)
{
string EmpShift = "";
ProductionWorker productionWorker = new ProductionWorker();
productionWorker.EmployeeName = txtName.ToString();
EmployeeName = productionWorker.EmployeeName; //Added mostly because I couldn't get EmployeeName to show anything in the messagebox
productionWorker.EmployeeNumber = Convert.ToInt32(txtIdNumb.text);
productionWorker.HourlyPayRate = Convert.ToInt32(txtPay.text);
EmpShift = Convert.ToString(txtShift.text);
txtName.Text = "";
txtIdNumb.Text = "";
txtPay.Text = "";
txtShift.Text = "";
}
private void btnShow_Click(object sender, EventArgs e)
{
MessageBox.Show("Name " + EmployeeName + "IDNumber " + EmployeeNumber + "Hourly rate " + txtPay + "Shift " + txtShift);
}
}
}
The code itself isn't showing any errors, but when I try to run it I get:
The string EmpShift thing is in there because I couldn't figure out how to work with the shift code more or less am using that as a place holder until I finger it out. I have no idea how to fix the problem, hopefully its a little mistake.
Thanks to help from the commets I was able to fix the first problem I had, now I'm having a problem with the message box at the end. The information I put into it is, Glitter for name, 12 for ID number, 1 for shift, and 12 for pay. Here's what its showing:
Name System.Windows.Forms.TextBox, Text: GlitterIDNumber 0Hourly rate
System.Windows.Forms.TextBox, Text: Shift SystemWindowsForm.TextBox, Text:
Convert.ToString doesnt give you an error because one of it calls its overload with object - public static string ToString(object value). However, since you are interested in user entered value, please use - TextBox.Text property instead of passing the TextBox.
Update 1 : some insides about this behavior
System.Convert.ToString(object value) is implemented as follows in .net -
public static string ToString(Object value, IFormatProvider provider) {
IConvertible ic = value as IConvertible;
if (ic != null)
return ic.ToString(provider);
IFormattable formattable = value as IFormattable;
if (formattable != null)
return formattable.ToString(null, provider);
return value == null? String.Empty: value.ToString();
}
therefore it ends up calling TextBox.ToString()
and System.Convert.ToInt32(object value) is as follows
public static int ToInt32(object value) {
return value == null? 0: ((IConvertible)value).ToInt32(null);
}
therefore an invalid cast exception because of this - ((IConvertible)value).ToInt32(null)
Update 2 : Code refactored for it to work
public partial class frmMainClasses : Form
{
//Change 1
//I have removed all class level string since they tend to make your code complicated & difficult to manage
//I'll replace all of them this a single instance of ProductionWorker class, a single object is easy to manage than a bunch
ProductionWorker productionWorker = new ProductionWorker(); // Creating the production Worker at class level
public class Employee
{
public string EmployeeName { get; set; }
public int EmployeeNumber { get; set; }
}
public class ProductionWorker : Employee
{
public float HourlyPayRate { get; set; }
public Shift Shift { get; set; }
}
public enum Shift
{
Day = 1,
Night = 2
}
public frmMainClasses()
{
InitializeComponent();
}
private void btxExit_Click(object sender, EventArgs e)
{
this.Close();
}
private void btnGetInfo_Click(object sender, EventArgs e)
{
//Change 2 : set the values of the class level variable
productionWorker.EmployeeName = txtName.Text; //.ToString(); // Change 3 removing the .ToString();
productionWorker.EmployeeNumber = Convert.ToInt32(txtIdNumb.Text);
productionWorker.HourlyPayRate = Convert.ToInt32(txtPay.Text);
productionWorker.Shift = (Shift)Enum.Parse(typeof(Shift), txtShift.Text);
//change 4 : using .ResetText() instead of Text
txtName.ResetText();// .Text = "";
txtIdNumb.ResetText();//.Text = "";
txtPay.ResetText();//.Text = "";
txtShift.ResetText();//.Text = "";
}
private void btnShow_Click(object sender, EventArgs e)
{
// change 5 : accessing class level productionWorker instead of bunch of strings
MessageBox.Show("Name " + productionWorker.EmployeeName + " IDNumber " + productionWorker.EmployeeNumber + " Hourly rate " + productionWorker.HourlyPayRate + " Shift " + productionWorker.Shift);
}
}
I've added comments to elaborate what all changes I've made, please write me a comment if you have any questions.
Also, at the moment your code does not validate user inputs in text boxes.
Related
I am new to WPF and I am trying to figure out how to create an "Update" button that will show all the contents of a row on a table, allowing the user to change any category and save the new data.
What the main window would look like :
Then when the update button is clicked, a window looking like this would pop up. :
How would you make the second window? Down below is what I have to show the main window without an "update" button.
**MainWindowxaml.cs**
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections;
using System.IO;
namespace Sort_a_list
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public class Student
{
public string name
{
get;
set;
}
public int age
{
get;
set;
}
public string gender
{
get;
set;
}
public string major
{
get;
set;
}
public string classification
{
get;
set;
}
}
public MainWindow()
{
InitializeComponent();
List<Student> user = new List<Student>();
try
{
using (StreamReader sr = new StreamReader(#"C:\Users\justi\Documents\2021 Self Study\WPF C#\Samples.txt"))
{
string line;
char[] sep = { ',' };
int length;
ArrayList rows = new ArrayList();
while ((line = sr.ReadLine()) != null)
{
string[] words = line.Split(sep);
length = words.Length;
rows.Add(words);
}
string[] columns;
for(int i = 1; i < rows.Count; i++)
{
columns = (string[])rows[i];
user.Add(new Student() { name = columns[0], age = Int16.Parse(columns[1]), gender = columns[2], major = columns[3], classification = columns[4] });
}
}
}
catch(Exception e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
sort.ItemsSource = user;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
}
}
}
Please help! Thank you very much!
You won't be able to access your Window1's DataGrid from Window2 directly.
You also not have access to your source collection (List) from Window2 to modify it from there.
In that facts, you got 2 ways:
use external database;
create public fixed collection of Students.
First of all and in any way I strongly recommend you to add some ID field to your Student object to be able unify each student.
If use external database, you can simply call something like "UPDATE students s SET s.name = #name, s.age = #age... WHERE s.ID = #id" from your Window2 when Save button clicked. #name, #age ... is new modified values
If use public fixed collection, you can access it from any part of your program.
When Window2 Save button clicked, you can search for student in it by student's ID and simply edit him. After Window2 closing you need just refresh DataGrid view by resetting ItemsSource.
It may look like this:
Student class:
public class Student
{
// Need to be unique for each student
public int ID { get; private set; }
public string Name { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
public string Major { get; set; }
public string Classification { get; set; }
public Student(int id)
{
ID = id;
Name = "SomeName";
Age = -1;
Gender = "Unknown";
Major = "Unknown";
Classification = "None";
}
// May also be overloaded with id, id+name, id+name+age, id+name+age+gender etc
public Student(int id, string name, int age, string gender, string major, string classification)
{
ID = id;
Name = name;
Age = age;
Gender = gender;
Major = major;
Classification = classification;
}
// If you need some kind of string representation of Student
public override string ToString()
{
return $"{ID},{Name},{Age},{Gender},{Major},{Classification}";
}
}
Fixed and public collection class to store Students:
public static class DB
{
// Your actual Database, where Students would be stored
private static readonly List<Student> students = new List<Student>();
// You can get it by DB.Students from anywhere
public static List<Student> Students { get { return students; } }
// As I see you use a file as source for item collection.
// You can add some Save() method to rewrite you existing
// file with items from "database":
// public static void Save()
// {
// StringBuilder sb = new StringBuilder();
//
// foreach (Student student in students)
// {
// sb.AppendLine(student.ToString());
// }
//
// File.WriteAllText("PathToYourFile", sb.ToString());
// }
//
// You should also override ToString method in Student class
// with something like (in format you wish):
// public override string ToString()
// {
// return $"{ID},{Name},{Age},{Gender},{Major},{Classification}";
// }
}
}
Update button click handler at Window1:
private void ButtonUpdate_Click(object sender, RoutedEventArgs e)
{
// There should be selected only 1 item or use dataGrid.SelectedItems[0]
if (dataGrid.SelectedItem is Student student)
{
// Pass selected Student to Window2
// where user will edit it
Window2 w2 = new Window2(student);
// Subscribe to Closed window to refresh DataGrid view after Student editing
w2.Closed += (s, a) =>
{
// Refresh the view of DataGrid by resetting its ItemsSource property
dataGrid.ItemsSource = null;
dataGrid.ItemsSource = DB.Students;
};
// Show update window
w2.ShowDialog();
}
}
And some kind of Window2:
public partial class Window2 : Window
{
// Here would be a copy of Student object from Window1
// with which we would manipulate in Window2
// while editing in its fields
private readonly Student editableStudent = null;
public Window2(Student student)
{
InitializeComponent();
// Copy student object to store it in our Window2
// and be able to modify it not only from Constructor
editableStudent = student;
// Fill Window2 fields with existing Student values
tbName.Text = student.Name;
tbAge.Text = student.Age.ToString();
tbGender.Text = student.Gender;
tbMajor.Text = student.Major;
tbClassification.Text = student.Classification;
// Easy "on-the-fly" subscribe to each field TextChanged handlers to check,
// whether some data was changed/edited or not
// and save it to editableStudent
tbName.TextChanged += (s, a) =>
{
// Comparing value in field with existing Student's value
if (tbName.Text != student.Name) // May also check for not empty / or for min input length
{
// Saving new value to a copied object of our Student
editableStudent.Name = tbName.Text;
}
};
// Don't forget to check for integer value
// and convert in back to int:
// Convert.ToInt32(tbAge.Text)/int.Parse(tbAge.Text)/int.TryParse(tbAge.Text, out int age)
tbAge.TextChanged += (sender, args) => { /* Do same as with Name */ };
tbGender.TextChanged += (sender, args) => { /* Do same as with Name. */ };
tbMajor.TextChanged += (sender, args) => { /* Do same as with Name */ };
tbClassification.TextChanged += (sender, args) => { /* Do same as with Name */ };
}
private void ButtonSave_Click(object sender, RoutedEventArgs e)
{
// Find index of Student element in our "Database" (List)
int index = DB.Students.FindIndex(x => x.ID == editableStudent.ID);
if (index != -1)
{
// Update record in a collection if it was found
DB.Students[index].Name = editableStudent.Name;
DB.Students[index].Age = editableStudent.Age;
DB.Students[index].Gender = editableStudent.Gender;
DB.Students[index].Major = editableStudent.Major;
DB.Students[index].Classification = editableStudent.Classification;
// Instead of use 'editableStudent' field with copied in
// constructor student's object, you can create it here
// and fill with values from TextBoxes in Window2.
// Or not create new Student object and fill new values
// directly in "database" by index.
// But you anyway need to store at least student's ID from
// student's object, passed from Window1, to be able to
// find him in "database"
// Student modifiedStudent = new Student(...);
// modifiedStudent.Name = tbName.Text;
// if (int.TryParse(tbAge.Text, out int age))
// modifiedStudent.Age = age;
// ...
// DB.Students[index].Name = modifiedStudent.Name;
// DB.Students[index].Age = modifiedStudent.Age;
// ...
// or
// DB.Students[index].Name = tbName.Text;
// if (int.TryParse(tbAge.Text, out int age))
// DB.Students[index].Age = age;
// ...
}
else
{
// Or message user if not found
MessageBox.Show("Student not found in Database (in a List of Students).");
}
// Close window after updating record in "Database"
// DataGrid view we will refresh from Window1 after
// Window2 close
Close();
}
private void ButtonCancel_Click(object sender, RoutedEventArgs e)
{
// Do nothing with Student, just close
Close();
}
}
I have a class with two properties: weigh and Id. I want to trigger an event when weigh is set. The event to be triggered is a messageBox showing the Id property. The Messagebox is shown, but it doesn't include the Id property.
Here's the entire code:
https://pastebin.com/zpHn48gL
public class MyClass
{
//Custom type Event declaration
public event EventHandler<Mas4TEventArgs> Info;
decimal _weigh;
//properties
public string Id { get; set; }
public decimal Weigh
{
get { return this._weigh; }
set //When this property is changed, invoke Info Event, passing Id property to be shown on messagebox.
{
this._weigh= value;
Info?.Invoke(this, new Mas4TEventArgs(this.Id));
}
}
}
public class Mas4TEventArgs : EventArgs
{
//constructor
public Mas4TEventArgs(string pId) { IdArgu = pId; }
//property IdArgu
public string IdArgu { get; set; }
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MyClass C = new MyClass();
//suscription
C.Info += C_Info;
//Function to be triggered by the event
void C_Info(object sendr, Mas4TEventArgs ev)
{
try
{ //ev.IdArgu doesn't show on the messagebox.
MessageBox.Show("Evento consumido. " + " Id: " + ev.IdArgu);
}
catch (Exception) { }
}
//properties
C.Weigh = Convert.ToDecimal(textBox1.Text);
C.Id = TxtId.Text;
//just to check the two properties have been parsed correctly.This works as intended.
MessageBox.Show("Ingresado: Peso: " + C.Peso.ToString() + " Id: " + C.Id);
}
}
or, if you prefer this:
https://lpaste.net/3710707699130826752
Your code includes the following key lines...
C.Weigh = Convert.ToDecimal(textBox1.Text);
C.Id = TxtId.Text;
Notice that the Id is being set after the Weigh. So at the point where the Weigh value is being set, it will raise an event with whatever was in Id before you set Id on the next line.
Swap the two lines over so that Id is set first, and your code will behave as you are expecting.
In my Windows form I have 2 text boxes namely, start odometer reading and end odometer reading. My goal is to subtract the "start reading" from the "end reading" and display the difference in the label next to the Name and phone number of the client in the windows form label.
How do I return the value of the method getMilesCharge() and display it on the confirmLabel?
Code for the Car Rental Class
//A class that represents the Rental Agency Class.
namespace Assignment1
{
partial class RentalAgencyClass
{
//instance variables
public string customerName { get; set; }
public string phoneNumber { get; set; }
public double sMiles { get; set; }
public double eMiles { get; set; }
public double noOfDays { get; set; }
private double DAY_CHARGE = 15;
private double MILE_CHARGE = 0.12;
//Constructor class
//sets the value of the starting and ending miles.
//sets the value of the number of days the car was rented for
public RentalAgencyClass(double startMiles, double endMiles, double days)
{
startMiles = sMiles;
endMiles = eMiles;
days = noOfDays;
}
//method to calculate the number of miles driven on the rental
public double getMileCharge()
{
double milesDriven = 0;
milesDriven = eMiles - sMiles;
return milesDriven * MILE_CHARGE;
}
//method to calculate the Day Charges on the rental
public double getDayCharge()
{
return noOfDays * DAY_CHARGE;
}
//Property to display the information on the label
public string GetInfo()
{
return customerName + " | " + phoneNumber + " | " + getDayCharge() +" miles";
}
}
}
Form Designer Class code
namespace Assignment1
{
public partial class RentalAgencyClass : Form
{
RentalAgencyClass aCarRental;
public RentalAgencyClass()
{
InitializeComponent();
}
private void calculateButton_Click(object sender, EventArgs e)
{
try
{
//instantiates object
aCarRental = new RentalAgencyClass();
aCarRental.customerName = nameTextBox.Text;
aCarRental.phoneNumber = phoneTextBox.Text;
//aCarRental. = getDayCharge();
// aCarRental.milesDriven = //store the difference in this variable
//displayLabel.Text = "(student information saved)";
}
catch (Exception err)
{
MessageBox.Show(err.Message, "Error");
}
//Displays information about the Rental
confirmLabel.Text = aCarRental.GetInfo();
}
}
}
By calling aCarRental = new RentalAgencyClass(); within your calculateButton_Click method you are calling the parameterless constructor of your partial class RentalAgencyClass, which means in your case, you are creating a new instance of your form instead of setting your properties. So sMiles and eMiles will stay by their default value 0.
To get your code working you have to do several steps.
At first I recommend you should split your form and your agency class.
So let's say, rename your form class to RentalCalculator. As a next step you have to/can remove the partial from your RentalAgencyClass, because it is not a part of your form class anymore and I assume you did not want to extend your class in another part of your code.
As LarsTech pointed out in the comments. You should now fix your RentalAgencyClass constructor to:
public RentalAgencyClass(double startMiles, double endMiles, double days)
{
this.sMiles = startMiles;
this.eMiles = endMiles;
this.noOfDays = days;
}
and may add the following property to your class
public double milesDriven
{
get
{
return this.eMiles - this.sMiles;
}
}
At least you have to change your event handler:
private void calculateButton_Click(object sender, EventArgs e)
{
try
{
// if not existing you have to create some input textboxes
double startMiles = Convert.ToDouble(startMilesTextBox.Text);
double endMiles = Convert.ToDouble(endMilesTextBox.Text);
double days = Convert.ToDouble(daysTextBox.Text);
// Hint: you are creating a new instance on every button click
// and overwriting your field in your form class.
aCarRental = new RentalAgencyClass(startMiles, endMiles, days);
aCarRental.customerName = nameTextBox.Text;
aCarRental.phoneNumber = phoneTextBox.Text;
// Store the result in local variables
// if you want to do something with them later
double dayCharge = aCarRental.getDayCharge();
double milesCharge = aCarRental.getMilesCharge();
double drivenMiles = aCarRental.milesDriven;
// displayLabel.Text = "(student information saved)";
}
catch (Exception err)
{
MessageBox.Show(err.Message, "Error");
}
//Displays information about the Rental
confirmLabel.Text = aCarRental.GetInfo();
}
Answering your question:
How do I return the value of the method getMilesCharge() and display it on the confirmLabel?
You will have to change the following line in your calculateButton_Click method from:
confirmLabel.Text = aCarRental.GetInfo();
to:
confirmLabel.Text = aCarRental.getMilesCharge().ToString();
Last but not least let me give you a kind advice.
You may take a look at the Microsoft Naming Guidelines.
For example: Properties should be named in PascalCasing.
But this is just my personal opinion.
I have the following, and it works:
My player class:
public Player(string Str, string SP)
{
Strength = Str;
StatPoints = SP;
}
public string StatPoints
{
get;
set;
}
public string Strength
{
get;
set;
}
Now on my form1 I have a textbox, and a button. The button increments the value in the textbox by one so long as there is a value above 0 in the SP textbox. Problem is, I am declaring six variables in order to manage two values because I have to convert strings to ints and all that crap. Is there a way to replace text boxes with something that is inherently int? Here is my character sheet code so far.
private void AddButton_Click(object sender, EventArgs e)
{
Player PCStats = new Player(StrBox.Text, SPBox.Text);
int IntPCSP = Convert.ToInt16(PCStats.StatPoints);
int IntPCStr = Convert.ToInt16(PCStats.Strength);
if (IntPCSP >= 1 && IntPCStr <= 7)
{
IntPCStr++;
IntPCSP--;
PCStats.Strength = IntPCStr.ToString();
PCStats.StatPoints = IntPCSP.ToString();
StrBox.Text = PCStats.Strength;
SPBox.Text = PCStats.StatPoints;
}
else
{
MessageBox.Show("Earn more experience!");
}
/*
MessageBox.Show("PCStats.StatPoints equals" + PCStats.StatPoints);
MessageBox.Show("PCStats,Strength equals" + PCStats.Strength);
MessageBox.Show("IntPCSP Equals" + IntPCSP.ToString());
MessageBox.Show("IntPCStr Equals" + IntPCStr.ToString());
*/
}
Or is there an even easier way to do this I completely overlooked. I was super excited to finally get this bit to work after a lot of trial and error, but I am open to redoing it. I would rather however just replace the text boxes so I am not converting variables all over the place.
This is quick go, not at a computer with Visual Studio on it but should give you a start. Also, try naming your variables etc to have a bit more meaning. Also, this is to fix what you has as-is but see my update / suggestion further down about moving logic into the Player class...
My player class:
public Player(int strength, int statPoints)
{
this.Strength = strength;
this.StatPoints = statPoints;
}
public int StatPoints { get; set; }
public int Strength { get; set; }
My Form:
private void AddButton_Click(object sender, EventArgs e)
{
Player thePlayer = new Player(int.Parse(StrBox.Text), int.Parse(SPBox.Text));
if (thePlayer.StatPoints > 0 && thePlayer.Strength < 8)
{
thePlayer.Strength++;
thePlayer.StatPoints--;
StrBox.Text = thePlayer.Strength.ToString();
SPBox.Text = thePlayer.StatPoints.ToString();
}
else
{
MessageBox.Show("Earn more experience!");
}
}
Obviously you would need to check that the values in the text box were integers. You could use another control, mask the text box etc or on the code replace int.Parse with int.TryParse which checks it is possible before conversion. Just a few ideas to get you going!
- UPDATE -
Another thing you could do is more the logic into the Player class. This is better as it keep the logic contained in one place so you can see what a Player can DO rather than having to search the whole program:
New Player class:
// The Player class
public class Player
{
// Constructor
public Player(int strength, int statPoints)
{
this.Strength = strength;
this.StatPoints = statPoints;
}
// Method to gain strength if enough StatPoints
public bool GainStrength()
{
bool playerHasEnoughStatPoints = true;
if (this.StatPoints < 1)
{
playerHasEnoughStatPoints = false;
}
else if (this.Strength < 8)
{
this.Strength++;
this.StatPoints--;
}
return playerHasEnoughStatPoints;
}
// Property for StatPoints
public int StatPoints { get; set; }
// Property for Strength
public int Strength { get; set; }
}
New Form:
// The Form or similar
public class MyFormOrSimilar
{
// When button pressed try and add strength to the player
protected void AddButton_Click(object sender, EventArgs e)
{
// Create new INSTANCE of the player and try to give them strength
Player thePlayer = new Player(int.Parse(StrBox.Text), int.Parse(SPBox.Text));
if (thePlayer.GainStrength())
{
StrBox.Text = thePlayer.Strength.ToString();
SPBox.Text = thePlayer.StatPoints.ToString();
}
else
{
MessageBox.Show("Earn more experience!");
}
}
}
I'm creating a form to hold information from "meetings". The user will fill out info regarding title, location, startTime, endTime, notes, and a date. What I am currently working on is the "save changes" button which will:
clear all the TextBoxes.
store the input in an array.
display only the title in the ListBox.
when the title is clicked on in the ListBox, the info stored in that array element re-populates in the appropriate TextBoxes should the user wish to make changes.
I have completed #1, #2 and #3 I would appreciate any help for #4. I've pasted the coding below for your viewing.
public partial class CalendarForm : Form
{
int currentIndex;
int arraySize = 0;
Meeting[] meetingArray = new Meeting[100];
public CalendarForm()
{
InitializeComponent();
}
private void saveChangesButton_Click(object sender, EventArgs e)
{
meetingArray[arraySize] = new Meeting();
meetingArray[arraySize].title = textBoxTitle.Text;
meetingArray[arraySize].location = textBoxLocation.Text;
meetingArray[arraySize].startTime = textBoxStartTime.Text;
meetingArray[arraySize].endTime = textBoxEndTime.Text;
meetingArray[arraySize].notes = notesTextBox.Text;
currentIndex = arraySize;
arraySize++;
meetingListBox.Enabled = true;
textBoxTitle.Text = "";
textBoxLocation.Text = "";
textBoxStartTime.Text = "";
textBoxEndTime.Text = "";
notesTextBox.Text = "";
*edit* added these two lines which now add the title to the listBox
meetingListBox.Items.Add(meetingArray[currentIndex].title);
Controls.Add(meetingListBox);
}
}
public class Meeting
{
public string title;
public string location;
public string startTime;
public string endTime;
public string notes;
};
This is how I would refactor the class:
public partial class CalendarForm : Form
{
private List<Meeting> Meetings { get; set; }
public CalendarForm()
{
InitializeComponent();
Meetings = new List<Meeting>();
}
private void saveChangesButton_Click(object sender, EventArgs e)
{
try
{
Meeting meeting = CreateMeeting();
Meetings.Add(meeting);
meetingListBox.Add(meeting);
}
catch
{
//Add proper error handling here
}
}
private Meeting CreateMeeting()
{
return new Meeting()
{
Title = textBoxTitle.Text,
Location = textBoxLocation.Text
StartTime = DateTime.Parse(textBoxStartTime.Text),
EndTime = DateTime.Parse(textBoxEndTime.Text),
Notes = notesTextBox.Text,
};
}
}
//As Matt Burland answered already:
private void meetingListBox_SelectedIndexChanged(object sender, EventArgs e)
{
Meeting meeting = meetingListBox.SelectedItem as Meeting;
if (meeting != null)
{
textBoxTitle.Text = meeting.Title;
//...etc for all your other text boxes.
}
}
public class Meeting
{
public string Title { get; set; }
public string Location { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public string Notes { get; set; }
public override string ToString()
{
return Title;
}
}
I've made a number of changes, more notably the switch from an Array to a List<>. Lists are more flexible and provide better functionality. Unless you really really need to use arrays, I would stay away from them just to better safeguard against logic errors index out of bounds type issues.
Also, I personally believe that dates should be stored in the DateTime struct format, but that is again a matter of preference. Note that it would be prudent to sanitize/validate the inputs (especially the dates) before assigning it into the Meeting object.
The Meeting object now has properties instead of public fields. Properties are preferred in case you ever want to change how something is Get/Set.
Hope this helps.
I really recommend you look up data binding and learn how to do this properly, but if you want a quick and dirty solution (although, in the end, you'll find it's a lot more work), I would do something like this:
private void saveChangesButton_Click(object sender, EventArgs e)
{
Meeting m = new Meeting();
m.title = textBoxTitle.Text;
m.location = textBoxLocation.Text;
m.startTime = textBoxStartTime.Text;
m.endTime = textBoxEndTime.Text;
m.notes = notesTextBox.Text;
meetingArray[arraySize] = m;
currentIndex = arraySize;
arraySize++;
meetingListBox.Enabled = true;
textBoxTitle.Text = "";
textBoxLocation.Text = "";
textBoxStartTime.Text = "";
textBoxEndTime.Text = "";
notesTextBox.Text = "";
meetingListBox.Items.Add(m);
//Controls.Add(meetingListBox); // You don't need to keep adding the control every time!
}
Now in your Meeting class, I'd override ToString() to just return the title. The ListBox will just use the ToString() method of whatever you add to it by default.
To help with #4, you want to bind the SelectedIndexChanged event and then use the SelectedItem property, cast it back to a Meeting object (because it'll return an Object) and then use it to repopulate your various text boxes.
Something like:
private void meetingListBox_SelectedIndexChanged(object sender, System.EventArgs e)
{
Meeting m = meetingListBox.SelectedItem as Meeting;
if (m != null)
{
textBoxTitle.Text = m.title;
//...etc for all your other text boxes.
}
}