c# getting the right form to show - c#

I have two forms a salaried employee and an hourly employee which has the employees details on it loading from a textfile. In my main form there is a listbox with the names of the employees, once one is clicked, i want to be able to press an edit employee details button on my main form and for the correct form to come up and I am struggling on how to do this. The code for my main form is here:
public partial class MainForm : Form
{
// The file used to store employee details
string employeesFile = "employees.txt";
// The collection used to hold the employee data
Employees employees;
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
employees = new Employees();
if (!employees.Load(employeesFile))
{
MessageBox.Show("Unable to load employees file");
}
else
{
PopulateListBox();
}
}
private void PopulateListBox()
{
listBoxEmployees.Items.Clear();
foreach (Employee employee in employees)
{
listBoxEmployees.Items.Add(employee.LastName + "," +
employee.FirstName);
}
listBoxEmployees.SelectedIndex = 0;
}
private void listBoxEmployees_DoubleClick(object sender, EventArgs e)
{ }
private void buttonEdit_Click(object sender, EventArgs e)
{
}
my load method:
{
public bool Load(string employeesFile)
{
bool status = false;
StreamReader inputFile = null;
string inputLine;
if (!File.Exists(employeesFile))
{
return false;
}
try
{
inputFile = new StreamReader(employeesFile);
if (inputFile != null)
{
inputLine = inputFile.ReadLine();
while (inputLine != null)
{
Employee employeeEntry =
EmployeeClass.NewEmployee(inputLine);
if (employeeEntry != null)
{
this.Add(employeeEntry);
}
inputLine = inputFile.ReadLine();
}
inputFile.Close();
}
status = true;
}
catch
{
}
return status;
}
}
the employees class code from the load method:
public class EmployeeClass
{
public static Employee NewEmployee(string employeeData)
{
if (employeeData.Length < 1)
{
return null;
}
switch (employeeData[0])
{
case 'S':
return new SalariedEmployee(employeeData);
case 'H':
return new HourlyEmployee(employeeData);
default:
return null;
the hourly employee form:
public partial class Hourly_Employee : Form {
HourlyEmployee _employeeEntry;
public Hourly_Employee()
{
InitializeComponent();
}
public HourlyEmployee employeeEntry
{
get
{
return _employeeEntry;
}
set
{
_employeeEntry = value;
}
}
private void Hourly_Employee_Load(object sender, EventArgs e)
{
textBoxlastName.Text = _employeeEntry.LastName;
textBoxfirstName.Text = _employeeEntry.FirstName;
textBoxaddress.Text = _employeeEntry.Address;
textBoxpostCode.Text = _employeeEntry.PostCode;
textBoxphoneNumber.Text = _employeeEntry.PhoneNumber;
dateTimePickerdateOfBirth.Text =
_employeeEntry.DateOfBirth.ToString();
textBoxhourlyPay.Text = _employeeEntry.HourlyPay.ToString();
textBoxoverTimePay.Text = _employeeEntry.OvertimePay.ToString();
}
}
and lastly my salaried employee form:
public partial class Salary_Employee : Form
{
SalariedEmployee _employeeEntry;
public SalariedEmployee employeeEntry
{
get
{
return _employeeEntry;
}
set
{
_employeeEntry = value;
}
}
private void Salary_Employee_Load(object sender, EventArgs e)
{
textBoxlastName.Text = _employeeEntry.LastName;
textBoxfirstName.Text = _employeeEntry.FirstName;
textBoxaddress.Text = _employeeEntry.Address;
textBoxpostCode.Text = _employeeEntry.PostCode;
textBoxphoneNumber.Text = _employeeEntry.PhoneNumber;
dateTimePickerdateOfBirth.Text =
_employeeEntry.DateOfBirth.ToString();
textBoxSalary.Text = _employeeEntry.Salary.ToString();
}
any help with this issue would be great!!

The trick is to add the employee objects to the listbox instead of only strings containing the employee names. This allows you to retrieve the selected employee directly from the listbox. Otherwise you would need a way to find the employee object belonging to a name.
Use the type of the selected item to determine the employee type and the employee form.
private void buttonEdit_Click(object sender, EventArgs e)
{
// Get the selected employee from the listBox.
object employee = listBoxEmployees.SelectedItem;
if (employee != null) { // An employee has been selected.
// Use the new C# 7.0 switch syntax in order to switch by employee type.
switch (employee) {
case SalariedEmployee sEmployee:
var sfrm = new Salary_Employee(); // Open the salaried employee form..
sfrm.employeeEntry = sEmployee;
sfrm.Show();
break;
case HourlyEmployee hEmployee:
var hfrm = new Hourly_Employee(); // Open the hourly employee form.
hfrm.employeeEntry = hEmployee;
hfrm.Show();
break;
}
}
}
In case you are using an older C# version you can test a type with
if (employee is SalariedEmployee) {
var frm = new Salary_Employee();;
frm.employeeEntry = (SalariedEmployee)employee;
frm.Show();
} else if (employee is HourlyEmployee) {
var frm = new Hourly_Employee();
frm.employeeEntry = (HourlyEmployee)employee;
frm.Show();
}
By default, an object's ToString method returns the name of the object's type. Enable the listbox to display the employees correctly by overriding the ToString method inherited from object in the common base class Employee.
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public override string ToString()
{
return LastName + ", " + FirstName;
}
}

Related

How can I update an object in a list using user selected index

I am trying to update an object in a list with a user selected index. I want to change the form title when the method is called and fill the textboxes with items from the selected object. I want to disable the studentname and studentID boxes so that the only text that can be updated are the grades. How do I use the index input to refer to the object in the list and change the specific components of the object?
namespace C03
{
public partial class frmAddStudent : Form
{
public frmAddStudent()
{
InitializeComponent();
}
private Student student = null;
public Student GetNewStudent()
{
this.ShowDialog();
return student;
}
public void UpdateStudent(int i)
{
this.Text = "Update Student Information";
}
}
}
namespace C03
{
public partial class frmStudentScores : Form
{
public frmStudentScores()
{
InitializeComponent();
}
private List<Student> students = null;
private void frmStudentScores_Load(object sender, EventArgs e)
{
students = StudentDB.GetStudent();
if (students.Count==0)
{
MessageBox.Show("No students on file at this time");
}
else
{
FillStudentListBox();
}
}
private void FillStudentListBox()
{
lstStudentsScores.Items.Clear();
foreach (Student s in students)
{
lstStudentsScores.Items.Add(s.DisplayStudInfo(4));
}
}
private void btnAdd_Click(object sender, EventArgs e)
{
frmAddStudent addStudent = new frmAddStudent();
Student student = addStudent.GetNewStudent();
if (student != null)
{
students.Add(student);
StudentDB.SaveStudents(students);
FillStudentListBox();
}
}
private void btnUpdate_Click(object sender, EventArgs e)
{
}
private void btnDelete_Click(object sender, EventArgs e)
{
int i = lstStudentsScores.SelectedIndex;
if (i != -1)
{
Student student = (Student)students[i];
string message = "Are you sure you want to delete " + student.DisplayStudInfo();
DialogResult button = MessageBox.Show(message, "Confirm Delete", MessageBoxButtons.YesNo);
if (button == DialogResult.Yes)
{
students.Remove(student);
StudentDB.SaveStudents(students);
FillStudentListBox();
}
else
{
MessageBox.Show("please select a student.");
lstStudentsScores.Focus();
lstStudentsScores.SelectedIndex = lstStudentsScores.Items.Count - 1;
}
}
}
}
}

How to link functions in form?

I try to do that the func Form1_Load will display the city list.
I dont know how can i link the 3 functions of the cities (JerusalemData(), LondonData(), OttawaData()) to the function FillCitiesData();
The problem is that it doesnt show the list but only the streets without choosing a city. Another problem - in HouseNum_ValueChanged it doesnt show numbers and you can also type letters and not just numbers.
This is my code - I'll be happy if anyone can help me find the problem.
namespace PlanYourParty
{
public partial class Form1 : Form
{
List <City> cities;
List <string> streets;
public Form1()
{
InitializeComponent();
FillCitiesData();
}
public void FillCitiesData()
{
cities = new List<City>();
cities.Add(new City() { Code = "123", Name = "Jerusalem" });
cities.Add(new City() { Code = "456", Name = "London" });
cities.Add(new City() { Code = "789", Name = "Ottawa" });
JerusalemData();
LondonData();
OttawaData();
}
private void Form1_Load(object sender, EventArgs e)
{
FillCitiesData();
cmbCity.DataSource = cities;
cmbCity.DisplayMember = "Name";
cmbCity.ValueMember = "Code";
cmbCity.SelectedIndexChanged += cmbCity_SelectedIndexChanged;
}
public void JerusalemData()
{
streets = new List<string>();
cmbStreet.Items.Clear();
cmbStreet.Items.Add("Admond Peleg");
cmbStreet.Items.Add("Pardes");
cmbStreet.Items.Add("Nayman");
}
public void LondonData()
{
streets = new List<string>();
cmbStreet.Items.Clear();
cmbStreet.Items.Add("Oxford Street");
cmbStreet.Items.Add("Piccadilly");
cmbStreet.Items.Add("Highfield Ave");
}
public void OttawaData()
{
streets = new List<string>();
cmbStreet.Items.Clear();
cmbStreet.Items.Add("Riverside Drive");
cmbStreet.Items.Add("Ontario Highway");
cmbStreet.Items.Add("Moodie Drive");
}
private void cmbCity_SelectedIndexChanged(object sender, EventArgs e)
{
if (sender != null && sender as City != null)
{
string code;
code = (sender as City).Code;
if (code == "123")
{
JerusalemData();
}
else if (code == "456")
{
LondonData();
}
else OttawaData();
}
}
private void cmbStreet_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void domainUpDownHouseNumber_SelectedItemChanged(object sender, EventArgs e)
{
}
private void Form1_Load_1(object sender, EventArgs e)
{
}
}
First I suggest you separate your data model from the UI. Pull everything you need to define cities and streets in the City class. I have included two methods that return the cities in the example, and the streets for each city.
No need for separate methods that do the same thing, but with different data.
City.cs
public class City
{
public string Code { get; set; }
public string Name { get; set; }
public IList<string> Streets { get => GetStreets(this); }
public static List<City> GetCities()
{
var cities = new List<City>();
cities.Add(new City() { Code = "123", Name = "Jerusalem" });
cities.Add(new City() { Code = "456", Name = "London" });
cities.Add(new City() { Code = "789", Name = "Ottawa" });
return cities;
}
public static List<string> GetStreets(City city)
{
var streets = new List<string>();
if (city == null) return streets;
switch (city.Code)
{
case "123":
streets.Add("Admond Peleg");
streets.Add("Pardes");
streets.Add("Nayman");
break;
case "456":
streets.Add("Oxford Street");
streets.Add("Piccadilly");
streets.Add("Highfield Ave");
break;
case "789":
streets.Add("Riverside Drive");
streets.Add("Ontario Highway");
streets.Add("Moodie Drive");
break;
default:
throw new ArgumentException("Unknown city code.");
}
return streets;
}
}
Then write the UI such that the controls contain the lists of items as specified by the City.GetCities() and City.GetSreets() methods.
The currently selected city and street are returned by CurrentCity and CurrentStreet as well as their corresponding index in the combobox in CurrentCityIndex and CurrentStreetIndex.
Form1.cs
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
cityComboBox.DataSource = City.GetCities();
cityComboBox.DisplayMember = nameof(CurrentCity.Name);
cityComboBox.ValueMember = nameof(CurrentCity.Code);
cityComboBox.SelectedIndexChanged += CityComboBox_SelectedIndexChanged;
cityComboBox.SelectedIndex = -1; // remove default selection of 1st item.
streetComboBox.DataSource = Array.Empty<string>();
streetComboBox.SelectedIndexChanged += StreetComboBox_SelectedIndexChanged;
}
private void CityComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
// TODO: Things when a city is selected.
streetComboBox.DataSource = CurrentCity?.Streets;
streetComboBox.SelectedIndex = -1; // remove default selection of 1st item.
UpdateLabels();
}
private void StreetComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
// TODO: Things when a street is selected.
UpdateLabels();
}
public void UpdateLabels()
{
cityInfo.Text = CurrentCityIndex >= 0 ? $"#{CurrentCity.Code} {CurrentCity.Name}" : "Please select a city.";
streetInfo.Text = CurrentStreetIndex >= 0 ? CurrentStreet : "Please select a street.";
}
public List<City> AllCities { get => cityComboBox.DataSource as List<City>; }
public List<string> AllStreets { get => streetComboBox.DataSource as List<string>; }
public int CurrentCityIndex { get => cityComboBox.SelectedIndex; }
public int CurrentStreetIndex { get => streetComboBox.SelectedIndex; }
public City CurrentCity { get => cityComboBox.SelectedItem as City; }
public string CurrentStreet { get => streetComboBox.SelectedItem as string; }
}
Screen Shots

Listview in virtual mode - get list of selected items

There is a way to get all items selected with the mouse in a list view when virtual mode is enabled for this winform.
Example of an working code in use, I can retrieve only one selected file for now. Not too much examples finded on the web and could be identified as duplicate but is not conclusive for me, or the answer is to simple.
private void FilesFoundList_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
try
{
if (e.ItemIndex >= 0 && e.ItemIndex < ListFilesInfos.Count)
{
try
{
var acc = ListFilesInfos[e.ItemIndex];
//with colors
e.Item = new ListViewItem(new string[] { acc.TagItem, acc.FileName, acc.FilePath.ToString() })
{ Tag = acc,
BackColor = SearchLabColor(0, Path.GetExtension(acc.FileName.ToString()), acc.FilePath.ToString(), acc.FileName.ToString()),
ForeColor = SearchLabColor(1, Path.GetExtension(acc.FileName.ToString()), acc.FilePath.ToString(), acc.FileName.ToString()),
UseItemStyleForSubItems = false
}; // Set Tag object property to our actual AccountInfo object
}
catch { this.Refresh(); }
}
}
catch
{
}
}
private void ShowItemsVirtual(List<SearchFilesInfo> infos)
{
try
{
FilesFoundList.VirtualListSize = infos.Count; // Set number of items in list view
}
catch { this.Refresh(); }
}
private void FilesFoundList_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
if (FilesFoundList.VirtualMode == true)
{
SelectedFiles.GlobalVar = (e.Item.SubItems[2]).Text.ToString() + (e.Item.SubItems[1]).Text.ToString();
}
}
You could abbreviate your code to:
List<multiSearchSelect> multiSearchSelect = new List<multiSearchSelect>();
private void FilesFoundList_VirtualItemsSelectionRangeChanged(object sender, ListViewVirtualItemsSelectionRangeChangedEventArgs e)
{
if (FilesFoundList.VirtualMode == true)
{
multiSearchSelect=
FilesFoundList.SelectedIndices
.Select(i=> new multiSearchSelect()
{
fileName = FilesFoundList.Items[i].SubItems[1].Text,
filePath = FilesFoundList.Items[item].SubItems[2].Text
});
}
}
class multiSearchSelect
{
public string fileName { set; get; }
public string filePath { set; get; }
}
I will post my solution that fits to my purpose. I have added ItemsSelectionRangeChanged event and get the list of file selected.
List<multiSearchSelect> multiSearchSelect = new List<multiSearchSelect>();
private void FilesFoundList_VirtualItemsSelectionRangeChanged(object sender, ListViewVirtualItemsSelectionRangeChangedEventArgs e)
{
if (FilesFoundList.VirtualMode == true)
{
multiSearchSelect.Clear();
ListView.SelectedIndexCollection col = FilesFoundList.SelectedIndices;
if (col.Count > 1)
{
foreach (int item in col)
{
multiSearchSelect.Add(new multiSearchSelect
{
fileName = FilesFoundList.Items[item].SubItems[1].Text,
filePath = FilesFoundList.Items[item].SubItems[2].Text
});
}
}
}
}
class multiSearchSelect
{
public string fileName { set; get; }
public string filePath { set; get; }
}

Loading a text file into a listbox

I am trying to load data into a listbox in a windows form application in c#. I have code from my main form which will put the data onto the listbox as followed...
namespace HRApplication
{
public partial class MainForm : Form
{
// The file used to store employee details
string employeesFile = "employees.txt";
// The collection used to hold the employee data
Employees employees;
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
employees = new Employees();
if (!employees.Load(employeesFile))
{
MessageBox.Show("Unable to load employees file");
}
else
{
PopulateListBox();
}
}
private void PopulateListBox()
{
listBoxEmployees.Items.Clear();
foreach (Employee employee in employees)
{
listBoxEmployees.Items.Add(employee.lastName + ", " +
employee.firstName);
}
//listBoxEmployees.SelectedIndex = 0;
}
from this I have a class called Employees where I am trying to get the load method working here is the code I have and any help would be very helpful.
namespace HRApplication
{
public class Employees : List<Employee>
{
public Employees()
{ }
public bool Load(string employeesFile)
{
List<string> lines = new List<string>();
using (StreamReader reader = new StreamReader("employees.txt"))
{
string line;
while ((line = reader.ReadLine()) != null)
{
lines.Add(line);
}
return true;
}
}
}
}
Suppose, for simplicity that your Employee class is something like this.
public class Employee
{
public string lastName {get;set;}
public string firstName {get;set;}
public override string ToString()
{
return lastName + ", " + firstName;
}
}
Now, when you load a line of text from the file you should split it in the parts that represent the employee data. Use that data to create an instance of the employee class and add the instance to the base class of Employees (a List<Employee>)
public bool Load(string employeesFile)
{
using (StreamReader reader = new StreamReader("employees.txt"))
{
string line;
while ((line = reader.ReadLine()) != null)
{
// Suppose that your line is splittable using a comma...
string[] temp = line.Split(',');
// This is really simplicistic. In a real world scenario
// you should check if the line contains correctly all the
// fields required to populate an Employee...
Employee emp = new Employee()
{
firstName = temp[0],
lastName=temp[1]
};
// This class is derived from List<T>
// so you can use the Add method
// to add the employee to itself...
Add(emp);
}
return true;
}
}
}
At this point your loop to populate the listbox should work (I use the ToString() overload to hide the building of the text for the ListBox)
private void PopulateListBox()
{
listBoxEmployees.Items.Clear();
foreach (Employee employee in employees)
{
listBoxEmployees.Items.Add(employee);
}
//listBoxEmployees.SelectedIndex = 0;
}

This C# public method is not returning a value

I have three classes, and the code is provided below.
Network - Add and Remove Phone, Process Calls. Phone1 and Phone2 can call each other when added to the network.
But I am having an issue when I am connecting both the phone to the network and trying to call phone1 to phone2; it is keeping giving me "receiver busy". I have tried to do a little debugging and read the status of phone2 when calling from phone1, but it returns an empty string (which should actually return "A", when it is added to the network as I am setting its value to "A").
public partial class network : Form
{
phone1 p1 = new phone1();
phone2 p2 = new phone2();
public network()
{
InitializeComponent();
}
public Boolean numberValidator(int number)
{
Boolean exist = false;
if (comboBox2.Items.Equals(number))
{
exist = true;
}
return exist;
}
public void processCall(int rNumber)
{
if (!numberValidator(rNumber))
{
p1.TextBox1.Clear();
p1.TextBox1.Text = "Not connected";
}
else
{
p1.TextBox1.Clear();
p1.TextBox1.Text = "Call in progress";
p2.receiveCall(1);
p1.setStatus("Busy");
/*
if (p2.btnCallPressStatus())
{
p1.TextBox1.Clear();
p1.TextBox1.Text = "Call initiated";
}*/
}
}
private void button1_Click(object sender, EventArgs e)
{
if (comboBox1.SelectedIndex == 0)
{
p1.Show();
comboBox2.Items.Add(1);
p1.setStatus("A");
}
if (comboBox1.SelectedIndex == 1)
{
p2.Show();
comboBox2.Items.Add(2);
p2.setStatus("A");
}
}
}
----------Phone1 Class---------
public partial class phone1 : Form
{
public phone1()
{
InitializeComponent();
}
string status;
public void setStatus(string Status)
{
status = Status;
}
public string returnStatus()
{
return status;
}
public void receiveCall(int callerNumber)
{
setStatus("Busy");
btnCall.Text = "Answer";
textBox1.Text = "Phone " + callerNumber + " Calling.";
}
public void makeCall(int number)
{
phone2 p2 = new phone2();
network net = new network();
MessageBox.Show(p2.returnStatus()); // this line not returing status of phone2
if (p2.returnStatus() == "A")
{
net.processCall(number);
}
else
{
textBox1.Text = "Receiver Busy";
}
}
public TextBox TextBox1
{
get
{
return textBox1;
}
}
private void btnCall_Click(object sender, EventArgs e)
{
string number = textBox1.Text;
int numberInt = Convert.ToInt16(number);
makeCall(numberInt);
}
string phoneNo = "";
private void btn2_Click(object sender, EventArgs e)
{
phoneNo = phoneNo + btn2.Text;
textBox1.Text = phoneNo;
}
}
-------------phone2 Class--------------
public partial class phone2 : phone1
{
public phone2()
{
InitializeComponent();
}
}
The routine makeCall is creating a new instance of phone2 and calling returnStatus next. The problem is that the string "status" is not Being initialized with any value when p2 is created, so, the returno value will never be "A" and you will always fail the test.

Categories

Resources