This is homework so if you can help thank you, if not I understand.
Everything work as intended. But I feel like I could implement things better or have cleaner code. I would like the button to just call a method that reads the JSON file, runs the inquiry and puts out the correct display without duplicating the code like I have.
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace EmployeePayDataWk4
{
public partial class Employee_Pay_Form : Form
{
public Employee_Pay_Form()
{
InitializeComponent();
}
private void Employee_Pay_Form_Load(object sender, EventArgs e)
{
EmployeeDataGridView.ColumnCount = 8;
EmployeeDataGridView.Columns[0].Name = "Employee Name";
EmployeeDataGridView.Columns[1].Name = "Zip Code";
EmployeeDataGridView.Columns[2].Name = "Age";
EmployeeDataGridView.Columns[3].Name = "Monthly Gross Pay";
EmployeeDataGridView.Columns[4].Name = "Department ID";
EmployeeDataGridView.Columns[5].Name = "Developer Type";
EmployeeDataGridView.Columns[6].Name = "Annual Taxes";
EmployeeDataGridView.Columns[7].Name = "Annual Net Pay";
}
private void LoadAllButton_Click(object sender, EventArgs e)
{
EmployeeDataGridView.Rows.Clear();
//Read from JSON file
string JSONstring = File.ReadAllText("JSON.json");
List<Employee> employees = JsonConvert.DeserializeObject<List<Employee>>(JSONstring);
//Display into DataGridView
foreach (Employee emp in employees)
{
string[] row = { emp.Name, emp.Zip, emp.Age.ToString(), string.Format("{0:C}", emp.Pay),
emp.DepartmentId.ToString(), SetDevType(emp.DepartmentId),
string.Format("{0:C}", emp.CalculateTax(emp.Pay)),
string.Format("{0:C}", AnnualPay(emp.Pay) - emp.CalculateTax(emp.Pay))};
EmployeeDataGridView.Rows.Add(row);
}
}
private void FTEmployeeButton_Click(object sender, EventArgs e)
{
EmployeeDataGridView.Rows.Clear();
//Read from JSON file
string JSONstring = File.ReadAllText("JSON.json");
List<Employee> employees = JsonConvert.DeserializeObject<List<Employee>>(JSONstring);
//LINQ Query for FT Employees
var FTEmp = from emp in employees
where emp.GetTaxForm == "W2"
select emp;
//Display into DataGridView
foreach (Employee emp in FTEmp)
{
string[] row = { emp.Name, emp.Zip, emp.Age.ToString(), string.Format("{0:C}", emp.Pay),
emp.DepartmentId.ToString(), SetDevType(emp.DepartmentId),
string.Format("{0:C}", emp.CalculateTax(emp.Pay)),
string.Format("{0:C}", AnnualPay(emp.Pay) - emp.CalculateTax(emp.Pay))};
EmployeeDataGridView.Rows.Add(row);
}
}
private void ContractEmployeeButton_Click(object sender, EventArgs e)
{
EmployeeDataGridView.Rows.Clear();
//Read from JSON file
string JSONstring = File.ReadAllText("JSON.json");
List<Employee> employees = JsonConvert.DeserializeObject<List<Employee>>(JSONstring);
//LINQ Query for Contract Employees
var contractEmp = from emp in employees
where emp.GetTaxForm == "1099"
select emp;
//Display into DataGridView
foreach (Employee emp in contractEmp)
{
string[] row = { emp.Name, emp.Zip, emp.Age.ToString(), string.Format("{0:C}", emp.Pay),
emp.DepartmentId.ToString(), SetDevType(emp.DepartmentId),
string.Format("{0:C}", emp.CalculateTax(emp.Pay)),
string.Format("{0:C}", AnnualPay(emp.Pay) - emp.CalculateTax(emp.Pay))};
EmployeeDataGridView.Rows.Add(row);
}
}
//Method to determine developer type
string typeName;
public string SetDevType(int id)
{
if (id == 1)
{
typeName = "Object-Oriented";
}
else if (id == 2)
{
typeName = "Scripts";
}
else { typeName = "Unknown"; }
return typeName;
}
public double AnnualPay(double amount) => 12 * amount;
}
class Employee : IFilingStatus
{
public Employee() { }
public string Name { get; set; }
public string Zip { get; set; }
public int Age { get; set; }
public double Pay { get; set; }
public int DepartmentId { get; set; }
public string GetTaxForm { get; set; }
public double CalculateTax(double basis)
{
double monthlyTax;
if ((GetTaxForm == "W2") || (GetTaxForm == "w2"))
{
monthlyTax = .07 * basis;
}
else
{
monthlyTax = 0;
}
return 12 * monthlyTax;
}
public double AnnualPay(double amount) => 12 * amount;
}
public interface IFilingStatus
{
double CalculateTax(double basis);
}
}
I would say this line:
List<Employee> employees = JsonConvert.DeserializeObject<List<Employee>>(JSONstring);
should be
IList<Employee> employees = JsonConvert.DeserializeObject<List<Employee>>(JSONstring);
for this reason.
local variables, private fields and parameters should be lowercase camel case, according to StyleCop:
string jsonString = File.ReadAllText("JSON.json");
The other thing is don't repeat yourself (DRY). These few lines can be refactored to be a separate method:
string JSONstring = File.ReadAllText("JSON.json");
List<Employee> employees = JsonConvert.DeserializeObject<List<Employee>>(JSONstring);
//LINQ Query for Contract Employees
var contractEmp = from emp in employees
where emp.GetTaxForm == "1099"
select emp;
In SetDevType you can totally use switch/case, which performs better.
string typeName; // why do we need this?
private string SetDevType(int id)
{
string typeName = string.Empty;
switch(id){
case 1: typeName = "Something"; break;
default: typeName = "Unknown";
}
return typeName;
}
some members of the class don't need to be public, such as
public double AnnualPay(double amount) => 12 * amount;
can be
private double AnnualPay(double amount) => 12 * amount;
and this method is somehow also in the Employee class, which is a Model class/POCO. POCO classes usually don't contain non-properties (although sometimes ToString and an empty constructor are included).
As I can see your Click event handlers are very similar.
I see only one change:
In your FTEmployeeButton_Click event handler you filter data like that:
var contractEmp = from emp in employees
where emp.GetTaxForm == "1099"
select emp;
And in ContractEmployeeButton_Click event handler you filter data like that:
var FTEmp = from emp in employees
where emp.GetTaxForm == "W2"
select emp;
Other code looks very similar. So we can define your code to one separate method...
But we need understand how filter your data.
For this purpose I suggest to use Tag property of Button class.
In this property you can save any object. In your case you can save GetTaxForm value.
So you can use only one event handler for all your buttons.
Please look next realization:
private void OnButton_Click(object sender, EventArgs e)
{
EmployeeDataGridView.Rows.Clear();
//Read from JSON file
string JSONstring = File.ReadAllText("JSON.json");
List<Employee> employees = JsonConvert.DeserializeObject<List<Employee>>(JSONstring);
object filter = ((Control)sender).Tag;
List<Employee> FTEmp;
if (filter != null) {
//LINQ Query for FT Employees
FTEmp = from emp in employees
where emp.GetTaxForm == filter.ToString()
select emp;
}
else
{
FTEmp = employees.ToList();
}
//Display into DataGridView
foreach (Employee emp in FTEmp)
{
string[] row = { emp.Name, emp.Zip, emp.Age.ToString(), string.Format("{0:C}", emp.Pay),
emp.DepartmentId.ToString(), SetDevType(emp.DepartmentId),
string.Format("{0:C}", emp.CalculateTax(emp.Pay)),
string.Format("{0:C}", AnnualPay(emp.Pay) - emp.CalculateTax(emp.Pay))};
EmployeeDataGridView.Rows.Add(row);
}
}
Related
I work in Windows Forms. I have a combobox ('Departments' name) it contains a list of departments. By selecting a department in comboBox1(Staff), employees working in this department appear. But I can't select an employee, because they are not displayed
Code, filling in comboBox1(Staff). dataNames - dictionary(department name - array of employees)
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (Departaments.SelectedItem != null)
{
this.Staff.Items.Clear();
var dataNames = DataForComdodox.ArrNames(Departaments.SelectedItem.ToString());
this.Staff.Items.AddRange(dataNames);
}
}
Code in Form1.Designer - comboBox1(Staff)
this.Staff.DrawMode = System.Windows.Forms.DrawMode.Normal;
this.Staff.FormattingEnabled = true;
this.Staff.Items.AddRange(new object[] {
});
this.Staff.Location = new System.Drawing.Point(374, 84);
this.Staff.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.Staff.Name = "Staff";
this.Staff.Size = new System.Drawing.Size(158, 21);
this.Staff.TabIndex = 0;
this.Staff.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
I tried to change Staff.SelectedIndex = 0, after I fill comboBox1(Staff) with values, but in the end, when choosing a department, an employee was selected automatically with an index of 0
If var dataNames = DataForComdodox.ArrNames(xx) returns a list or array of class employees, you could override the ToString() in the employee class.
public class Employee
{
public int EmpId { get; set; }
public string EmpName { get; set; }
public string DeptName { get; set; }
public override string ToString()
{
return $"{this.EmpId}: {this.EmpName}";
}
}
I have an Employee class that populates a listbox when I fill in text fields and click an add button. When the item gets added to the list it displays the object property and I need to figure out how to store the object in the list, but also list it by name.
Here's my Employee class:
class Employee
{
public string Name;
public string Position;
public DateTime BirthDate;
public DateTime StartDate;
public decimal Wage;
public Employee(string name, string position, DateTime birthDate, DateTime startDate, decimal wage)
{
Name = name;
Position = position;
BirthDate = birthDate;
StartDate = startDate;
Wage = wage;
}
}
Here is my button click event: (Where I populate the list)
private void btnAdd_Click(object sender, RoutedEventArgs e)
{
var employees = new List<Employee>();
var name = txtName.Text;
var position = txtPosition.Text;
DateTime birthDate = dpBirthDate.Date.DateTime;
DateTime startDate = dpStartDate.Date.DateTime;
var wageValue = txtWage.Text;
decimal wage = Decimal.Parse(wageValue);
employees.Add(new Employee(name, position, birthDate, startDate, wage));
foreach(Employee employee in employees)
{
lbEmployee.Items.Add(employee);
}
}
For the button click event in my for each loop I tried to list the object by doing this
foreach(Employee employee in employees)
{
lbEmployee.Items.Add(employee.Name);
}
This lists it by name but doesn't add the entire object so it breaks the function below
private void lbEmployee_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
{
Employee employee = (Employee)lbEmployee.SelectedItem;
if (employee != null)
{
txtName.Text = employee.Name;
txtPosition.Text = employee.Position;
dpBirthDate.Date = employee.BirthDate;
dpStartDate.Date = employee.StartDate;
txtWage.Text = Convert.ToString(employee.Wage);
}
}
You have to set
lbEmployee.DisplayMember = "Name";
in the designer and then you can add the employee in the items avoiding to break your function
class EmployeeDAL
{
private ArrayList _employees;
public EmployeeDAL()
{
_employees = new ArrayList();
_employees.Add(new Employee { EmployeeID = 1, EmployeeName = "Ram", Salary = 50000 });
_employees.Add(new Employee { EmployeeID = 2, EmployeeName = "Sahaym", Salary = 40000 });
_employees.Add(new Employee { EmployeeID = 3, EmployeeName = "Gopi", Salary = 55000 });
_employees.Add(new Employee { EmployeeID = 4, EmployeeName = "Prakash", Salary = 45000 });
_employees.Add(new Employee { EmployeeID = 5, EmployeeName = "Dheeraj", Salary = 60000 });
_employees.Add(new Employee { EmployeeID = 6, EmployeeName = "Shibhu", Salary = 50000 });
}
public bool DeleteEmployee(int id)
{
if (_employees.Contains(id))
{
_employees.Remove(id);
return true;
}
else
return false;
}
}
I want to delete an employee with specific id using DeleteEmployee(id) method. How can I do this in ArrayList ?
Hi as an answer to your question you can use the code below :
public bool DeleteEmployee(int id)
{
var employees = _employees.Cast<Employee>()
.Where(e => e.EmployeeID == id)
.Distinct();
if (employees.Count() == 0)
return false;
else
foreach (var employee in employees.ToList())
_employees.Remove(employee);
return true;
}
But in my opinion, if it's possible, you should use another type of collection like a List, it could be easier to handle than an ArrayList.
Forgive the crudeness of my code. But, sample of using a List follows:
using System;
using System.Collections.Generic;
using Gtk;
public partial class MainWindow : Gtk.Window
{
public class Employee
{
public int EmployID;
public string EmployeeName;
public int Salary;
public Employee(int v1, string v2, int v3)
{
this.EmployID = v1;
this.EmployeeName = v2;
this.Salary = v3;
}
}
public class Employees
{
public List<Employee> employees = null;
public bool Delete(int inID)
{
Employee buffer = employees.Find(x => x.EmployID == inID);
if (buffer != null)
{
employees.Remove(buffer);
return true;
}
return false;
}
}
public Employees Listof = new Employees();
public MainWindow() : base(Gtk.WindowType.Toplevel)
{
Build();
Listof.employees = new List<Employee>()
{
new Employee(1, "Ram", 50000),
new Employee(2, "Sahaym", 40000),
new Employee(3, "Gopi", 55000),
new Employee(4, "Prakash", 45000),
new Employee(5, "Dheeraj", 60000),
new Employee(6, "Shibhu", 50000)
};
label1.Text = "Employee Count: " + Listof.employees.Count.ToString();
}
protected void OnDeleteEvent(object sender, DeleteEventArgs a)
{
Application.Quit();
a.RetVal = true;
}
protected void OnButton3Pressed(object sender, EventArgs e)
{
label1.Text = $"Deleted Employee 3 successful : {Listof.Delete(3)}" +
" Employee Count: " + Listof.employees.Count.ToString();
}
I want to order a text file using LINQ by date and output all columns into a listbox.
For example the input file is:
Name,Age,DOB,Male
Mary,28,01/01/1991,False
Anne,29,06/06/1989,False
John,18,06/07/2000,True
class Name
{
public double Age { get; set;}
public string Name{ get; set; }
public DateTime Date { get; set; }
public string Male { get; set; }
public Name()
{
}
public Name(string name, double age, DateTime date, string male)
{
Course = course;
Amount = amount;
Date = date;
Male = male;
}
}
private IEnumerable<Name> ReadName()
{
List<Name> dataCollection = new List<Name>();
using (var f = new StreamReader(#"R:\Data.txt"))
{
string line = string.Empty;
while ((line = f.ReadLine()) != null)
{
var data = line.Split(',');
dataCollection.Add(new Name(data[0], Convert.ToDouble(data[1]),Convert.ToDateTime(data[2]), data[3]));
}
}
return dataCollection;
}
private void btnDOBOrder_Click(object sender, EventArgs e)
{
lstByDate.Items.Clear();
IEnumerable<Name> names = ReadName();
var DateOrder = name
.OrderByDescending(x => x.Date)
.ToList();
lstByDate.DataSource = DateOrder;
}
Name Age DOB Male
John 18 06/07/2000 True
Mary 28 01/01/1991 False
Anne 29 06/06/1989 False
The current output in the listbox is:
Form1.Name
Form1.Name
Form1.Name
You are writing on listbox the string representation of your Name Class? If yes you just have to override ToString method in your Name class to display what information you want
ListBox's display collections of ListItems, and those have Text and Value properties that control what they display. You could project your collection into an anonymous type before databinding, then set the the DataValueField and DataTextField to your computed properties. It could look something like this:
var DateOrder = names.OrderByDescending(x => x.Date)
.Select(x => new { Text = $"{x.Name} {x.Age} {x.DOB} {x.Male}", Value = x.Name })
.ToList();
lstByDate.DataSource = DateOrder;
lstByDate.DataValueField = "Value";
lstByDate.DataTextField = "Text";
Try ICompare :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Data;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication100
{
class Program
{
const string FILENAME = #"c:\temp\test.csv";
static void Main(string[] args)
{
Person person = new Person(FILENAME);
person.Sort();
}
}
public class Person : IComparable
{
public string Name { get;set;}
public int Age { get;set;}
public DateTime DOB { get;set;}
public string sex { get;set;}
List<Person> dataCollection = new List<Person>();
public Person() { }
public Person(string filename)
{
using (var f = new StreamReader(filename))
{
string line = string.Empty;
int rowCount = 0;
while ((line = f.ReadLine()) != null)
{
if (++rowCount > 1)
{
var data = line.Split(',');
dataCollection.Add(new Person() { Name = data[0], Age = Convert.ToInt32(data[1]), DOB = Convert.ToDateTime(data[2]), sex = data[3]});
}
}
}
}
public int CompareTo(object obj)
{
return this.DOB.CompareTo(((Person)obj).DOB);
}
public void Sort()
{
dataCollection.Sort();
}
}
}
I encountered a problem where I can't seem to make the names in the Combo Box appear once instead of multiple one. Is there anything in my codes that causes this problem? Any help will be greatly appreciated.
Below is the code to link the names to the combo Box.
private void Create_EmpDetails_Load(object sender, EventArgs e)
{
using (satsEntities Setupctx = new satsEntities())
{
var viewEmpName = (from viewEN in Setupctx.employees
join ufi u in Setupctx.ufis on viewEN.UFISID equals u.UFISID
select new { u.EmployeeName , u.UFISID}).Distinct().ToList();
cbName.DataSource = viewEmpName;
cbName.DisplayMember = "EmployeeName";
cbName.ValueMember = "EmployeeName";
//cbName.ValueMember = "UFISID";
}
}
Each of those rows has a different UFISID, so Distinct() is not removing them.
It sounds like you just want to show employees:
cbName.DataSource = Setupctx.Employees;
I edited to my codes to this and I managed to show only 1 name for instead of multiple records.
private void Create_EmpDetails_Load(object sender, EventArgs e)
{
using (satsEntities Setupctx = new satsEntities())
{
var viewEmpName = (from viewEN in Setupctx.employees
join ufi u in Setupctx.ufis on viewEN.UFISID equals u.UFISID
select new { u.EmployeeName }).Distinct().ToList();
cbName.DataSource = viewEmpName;
cbName.DisplayMember = "EmployeeName";
cbName.ValueMember = "EmployeeName";
//cbName.ValueMember = "UFISID";
}
}
Probably, it would be enough for you to replace
select new { u.EmployeeName , u.UFISID}
with
select new { u.EmployeeName }
in combobaxes we display the string as DisplayMember for users and id of members(maybe important for us) as ValueMember for us. more time we work with ids . my example :
class Country
{
public string Name { get; set; }
public int ID { get; set; }
public Country( int i,string s) { Name = s; ID = i; }
}
class ComboItem
{
public string DisplayMember { get; set; }
public int ValueMember { get; set; }
}
class ComboItemEqualityComparer : IEqualityComparer<ComboItem>
{
public bool Equals(ComboItem item1, ComboItem item2)
{
if (item1.ValueMember == item2.ValueMember && item1.DisplayMember == item2.DisplayMember)
{
return true;
}
return false;
}
public int GetHashCode(ComboItem item)
{
string str = item.DisplayMember + item.ValueMember;
return str.GetHashCode();
}
}
test :
List<Country> countries = new List<Country> {
new Country(1,"UK"),
new Country(2,"Turkey"),
new Country(8,"Turkey"),
new Country(5,"Turkey"),
new Country(2,"Turkey"),
new Country(3,"USA") ,
new Country(3,"USA")}; //.Distinct(new CountryEqualityComparer()).ToList();
var Data = (from i in countries
select new ComboItem { ValueMember = i.ID, DisplayMember = i.Name }).Distinct(new ComboItemEqualityComparer()).ToList();
cbName.DataSource = Data;
cbName.DisplayMember = "DisplayMember";
cbName.ValueMember = "ValueMember";
sometimes we have data that have displayname the same but the id of them arent. we can change the ComboItemEqualityComparer equals method to :
public bool Equals(ComboItem item1, ComboItem item2)
{
if (item1.ValueMember == item2.ValueMember )
{
return true;
}
return false;
}
enjoy.
for this question we can :
....
select new ComboItem { ValueMember = u.UFISID, DisplayMember = u.EmployeeName }).Distinct(new yourIEqualityComparer()).ToList();