Raise events in c# - help needed - c#

Hello I'm trying to raise an event when the Birthdate of a person is greater then the actual date.
I'm new with events and it doesn't seem to work.
Code is beneath,
namespace LibClassLuchthaven
{
public class Person
{
public DateTime Birthdate { get; set; }
public string Firstname { get; set; }
public Gender Gender { get; set; }
public string Name { get; set; }
public event EventHandler BirthdateInFuture;
public Person()
{
this.Birthdate = DateTime.Now;
this.Firstname = string.Empty;
this.Gender = Gender.unknown;
this.Name = string.Empty;
}
public Person(DateTime birthdate, string firstname, Gender gender, string name)
{
this.Birthdate = birthdate;
this.Firstname = firstname;
this.Gender = gender;
this.Name = name;
}
public void OnBirthdateInFuture()
{
if (BirthdateInFuture!=null)
{
if (this.Birthdate > DateTime.Now)
{
BirthdateInFuture(this, EventArgs.Empty);
}
}
}
public override string ToString()
{
return this.Name + ", " + this.Firstname + " - " + this.Birthdate + " ( +" + this.Gender + ")";
}
}
}
public partial class FormCrewManagement : Form
{
public Person person = new Person();
public FormCrewManagement()
{
InitializeComponent();
person.BirthdateInFuture += Person_BirthdateInFuture;
}
private void Person_BirthdateInFuture(object sender, EventArgs e)
{
MessageBox.Show("Birthdate is in the future");
}

Try Changing the Property
public DateTime Birthdate { get; set; }
to
private DateTime _birthDate;
public DateTime Birthdate
{
get {return _birthDate;}
set
{
_birthDate=value;
if(value > DateTime.Now)
BirthdateInFuture?.Invoke(this, EventArgs.Empty);
}
}
This will raise the event when Birthdate value is in future.

Philip,
there is no place in your code where the event is raised. You could create a property called BirthDate and in the setter part, raise the event. When the birthdate is changed to a future date, it would/could raise the event.

It looks like the problem may be a logical one, rather than anything to do with events. You are setting the birthday to today's date... then checking if it's later. It never will be.
public Person()
{
this.Birthdate = DateTime.Now;
if (BirthdateInFuture!=null)
{
if (this.Birthdate > DateTime.Now)
{
BirthdateInFuture(this, EventArgs.Empty);
}
}

Related

Having trouble using methods in custom classes in C#

I've created a class called "Person" and I'm trying to write a method called Birthday that would increase the attribute "Age" by one. I know it's dumb to try and define a variable using Age, but I can't figure out how to pass a variable from Main into Person.Birthday. I also probably don't need that while loop, but I was just trying a bunch of things. Anyway, help would be appreciated.
class Program
{
static void Main(string[] args)
{
Person p1 = new Person();
p1.Name = "Frank";
p1.Age = 30;
p1.Gender = "Male";
p1.Birthday();
Console.WriteLine(p1.Age);
Console.ReadLine();
}
class Person
{
public string Name { get; set; }
public string Gender { get; set; }
public int Age { get; set; }
public int Birthday()
{
int newAge = Age;
while (Age > 0)
{
newAge += 1;
break;
}
return newAge;
}
}
You have a couple issues with your code.
First you shouldnt be storing the "Age" of a person, you should be storing the Date they were born so that you can always calculate the Age.
public DateTime BirthDate { get; set; }
Second; consider the creation of a Person. In your code you create a new Person, then assign their Name, Gender and BirthDate properties. Is that really the best way of doing it? A Person has to have a Name, Gender and BirthDate right? Plus these properties don't change (or at least they shouldn't easily change). So make your Person class have a constructor accepting these arguments, and then make the setting of these properties private:
public string Name { get; private set; }
public string Gender { get; private set; }
public DateTime BirthDate { get; private set; }
public Person(string name, string gender, DateTime birthDate)
{
Name = name;
Gender = gender;
BirthDate = birthDate;
}
Then to calculate someone Age you can just compare the dates in a GetCurrentAge() method, then you can use your existing Age property but make it "read only" by just returning the value from GetCurrentAge():
public int Age => GetCurrentAge();
private int GetCurrentAge()
{
DateTime today = DateTime.Today;
int age = today.Year - BirthDate.Year;
if (BirthDate > today.AddYears(-age))
{
age--;
}
return age;
}
The code and calculation you are doing does not make sense but the bigger problem is that you should not store a calculated field. Instead store the date of birth and calculate the age. See also https://stackoverflow.com/a/1404/1260204 for how to calculate.
public class Person
{
public string Name { get; set; }
public string Gender { get; set; }
public DateTime BirthDate { get; set; }
public int Age
{ get {
// copied from https://stackoverflow.com/a/1404/1260204
var today = DateTime.Today;
var age = today.Year - BirthDate.Year;
if (birthdate > today.AddYears(-age)) {
age--;
}
return age;
}}
}
Calling the method
static void Main(string[] args)
{
Person p1 = new Person();
p1.Name = "Frank";
p1.Age = 30;
p1.Gender = "Male";
p1.BirthDate = new DateTime(1986, 5, 12);
Console.WriteLine(p1.Age);
Console.ReadLine();
}

Join two string properties (firstName + lastName) of usercontrol and assign it to label

I made a custom usercontrol which contains a label.
I have 3 string properties : firstName, lastName, fullName.
How can I set the label's text = FullName ?
public string firstName
{
get; set;
}
public string lastName
{
get; set;
}
public string fullName //this fails
{
get { return string.Format("{0} {1}", firstName, lastName); }
set { labelFullName.Text = value; }
}
Looks like Windows Form to me. In WPF you would be using labelFullName.Content property. Assuming you want to set the label as the fullname each time first name or last name changes, then one option would be to do this within your UserControl class:
private String _sFirstName = "";
private String _sLastName = "";
public String FirstName {
get { return _sFirstName; }
set { _sFirstName = value; UpdateLabel(); }
}
public String LastName {
get { return _sLastName; }
set { _sLastName = value; UpdateLabel(); }
}
public String FullName {
get { return _sFirstName + " " + _sLastName; }
}
private void UpdateLabel() {
// do within a UI thread to prevent threading issues
this.BeginInvoke((Action)(() => {
labelFullName.Text = this.FullName.Trim();
}));
}

Inconsistent accessibility Error in Program

I'm currently trying to C# asp.net and this was one of my old labs that I never attended and I'm looking for help on it.
Basically I want to be able to store details of the person I input onto a webpage and then bring them up in the About page.
I keep getting the error:
Error 1: Inconsistent accessibility: field type 'System.Collections.Generic.IList<Lab5.Person>' is less accessible than field 'Lab5._Default.PresentPerson'
My code:
Class Person:
{
class Person
{
string age;
string name;
string dob;
string telNo;
string gender;
string address;
public string Age
{
get { return age; }
set { age = value; }
}
public string Name
{
get { return name; }
set { name = value; }
}
public string DOB
{
get { return dob; }
set { dob = value; }
}
public string TelNo
{
get { return telNo; }
set { telNo = value; }
}
public string Gender
{
get { return gender; }
set { gender = value; }
}
public string Address
{
get { return address; }
set { address = value; }
}
public string enterPerson;
public Person(string name, string age, string dob, string telNo, string gender, string address)
{
Name = name;
Age = age;
DOB = dob;
TelNo = telNo;
Gender = gender;
Address = address;
}
public string PresentPerson()
{
return enterPerson = "Name: " + Name + "\n" + "Age: " + Age + "\n" + "Date of Birth: "
+ DOB + "\n" + "Telephone Number: " + TelNo + "\n" + "Gender: " + Gender + "\n" + "Address: "
+ Address;
}
}
}
Code behind the Default page:
{
public partial class _Default : Page
{
public static IList<Person> personList = new List<Person>();
protected void Button1_Click(object sender, EventArgs e)
{
Response.Write("You have successfully added a Person!");
personList.Add(new Person(TextBox1.Text, TextBox2.Text,
TextBox3.Text, TextBox4.Text, DropDownList1.Text, TextBox5.Text));
Session["Person"] = personList;
}
}
}
and code in the About page:
{
public partial class About : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Session["PersonList"] != null)
{
IList<Person> personList = (List<Person>)Session["PersonList"];
foreach (Person p in personList)
{
Response.Write(string.Format("Name :{0} and Age :{1}, DOB :{2}, TelNo, :{3}, Gender :{4}, Address :{5} ", p.Name, p.Age, p.DOB, p.TelNo, p.Gender, p.Address));
Response.Write("<br/>");
}
}
}
}
}
I know that there's probably a load of issues, but I am new to C#!
Your _Default page has a list of Person field. Person is internal, but _Default is public.
This is the inconsistency - clients of _Default would have access to these Person objects when they shouldn't. To fix, make Person public:
public class Person
{
....
You could, alternatively, make the field internal or private.
private static IList<Person> personList = new List<Person>();
You need to change class Person to public class Person
If something is public like the _Default class in your example every public thing on it also needs to be public. You can't have a public thing that is in fact private.

C# How correctly work get and set?

I am beginner in programming and I want to ask you probably the easiest question.
I did something like this:
class person
{
private string name;
public string surname;
private int year;
}
class student : person
{
}
class Program
{
static void Main(string[] args)
{
List<student> list = new List<student>();
list.Add(new student()
{
surname = "jordan"
// name ... ???
// year .. ?
});
}
}
How can I correctly use get and set if I have private field or how can I assign a value to name or year?
You can set private property in constructor like this:
public class person
{
private string name { get; set; };
public string surname { get; set; };
private int year { get; set; };
public person(string name, int year)
{
this.name = name;
this.year = year;
}
}
public class student : person
{
public student(string name, int year) : base (name, year) { };
}
and use can be:
list.Add(new student("name", 45)
{
surname = "jordan"
});
(Note the use of Upper case for classes and properties, lower case reserved for fields and local variables).
Declare as public properties like so:
class Person
{
public string Surname {get; set;}
}
Usage:
new Person{
Surname = "jordan"
};
Or with private setters, and set in constructor.
class Person
{
public Person(string surname)
{
Surname = surname;
}
public string Surname {get; private set;}
}
Usage:
new Person("jordan");
Or private fields, also set in constructor (same usage).
class Person
{
private string surname;
public Person(string surname)
{
this.surname = surname;
}
public string Surname {get{return surname;}}
}
Even if the fields are private you can provide public properties. You should do that anyway since the fields should not be accessible from outside, all the more if they are just backing fields for properties.
class person
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
private string surname;
public string Surname
{
get { return surname; }
set { surname = value; }
}
private int year;
public int Year
{
get { return year; }
private set { year = value; }
}
}
Now the fields are private and you can change the access modifiers of the properties according to your needs. You can even make the setter private as shown in the Year property.
List<Person> list = new List<Person>();
list.Add(new Person()
{
Name = "Michael",
Surname = "jordan",
});
Now you cannot modify the Year from outside since it's private. You could provide an appropriate constructor to initialize it.

C# array - "object reference not set to an instance of an object"

I am having a major issue making this work. All I need to do is make my array display.
namespace OOP_3
{
public partial class Add_Child : Form
{
public Add_Child()
{
InitializeComponent();
}
private void btnAddChild_Click(object sender, EventArgs e)
{
Mother m = new Mother();
m.MyChildren = new Child[3];
int ID = int.Parse(txtID.Text);
string FNAME = txtFname.Text;
string LName = txtLname.Text;
DateTime DOB = DateTime.Parse(txtDob.Text);
//Add children
label5.Text = m.GetMyChildrenDetails();
if (addtoarray(m,ID,FNAME,LName,DOB) == true)
{
MessageBox.Show("added", "Add Child");
}
else
{
MessageBox.Show("cannot add", "Child add - full");
}
}
public bool addtoarray(Mother m, int ID, string FNAME, string LName,DateTime DOB)
{
for (int i = 0; i < m.MyChildren.Length; i++)
{
if (m.MyChildren[i]== null)
{
m.MyChildren[i] = new Child(m); //See comment below
m.MyChildren[i].ChildId = ID;
m.MyChildren[i].FirstName = FNAME;
m.MyChildren[i].LastName = LName;
m.MyChildren[i].DateOfBirth = DOB;
return true;
}
}
return false;
}
}
}
From a code comment: This line destroys everything in the heap and recreate the array causing my to have values that will not show up in my label5.text ive been pondering researching for hours and i think iam either going insane or am just noobie at coding which iam :) please some help would be nice:)....
If needed, I will post my class's and main form up :)
public class Mother
{
//Fields
private int motherId;
private string firstName;
private string lastName;
private string mobile;
private Child[] myChildren; //mother "has a" many children
//props
public Child[] MyChildren
{
get { return myChildren; }
set { myChildren = value; }
}
public string Mobile
{
get { return mobile; }
set { mobile = value; }
}
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
public int MotherId
{
get { return motherId; }
set { motherId = value; }
}
//constructors
//methods
//Get Mother Details
public override string ToString()
{
return motherId + ", " + firstName + ", " + lastName + ", " + mobile;
}
//AddChild
public bool AddChild(Child myChild)
{
for (int i = 0; i < myChildren.Length; i++)
{
if (myChildren[i] != null)
{
myChildren[i] = myChild;
return true;
}
}
return false;
}
//GetMyChildrenDetails
public string GetMyChildrenDetails()
{
string msg = "";
for (int i = 0; i < myChildren.Length; i++)
{
if (myChildren[i] != null)
{
msg += "\n" + myChildren[i];
}
}
return msg;
}
public class Child
{
//fields
private int childId;
private string firstName;
private string lastName;
private DateTime dateOfBirth;
private Mother myMother; //child "has a" mother
//props
public Mother MyMother
{
get { return myMother; }
set { myMother = value; }
}
public DateTime DateOfBirth
{
get { return dateOfBirth; }
set { dateOfBirth = value; }
}
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
public int ChildId
{
get { return childId; }
set { childId = value; }
}
//constructors
//Child cannot be created without a mother
public Child(Mother myMother)
{
this.myMother = myMother;
}
//Child cannot be created without a mother
public Child(Mother myMother, int childId)
{
this.myMother = myMother;
this.childId = childId;
}
//methods
//Get Child Details
public override string ToString()
{
return childId + ", " + firstName + ", " + lastName + ", " + dateOfBirth;
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnRegister_Click(object sender, EventArgs e)
{
}
private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
}
private void closeToolStripMenuItem_Click(object sender, EventArgs e)
{
Close();
}
private void BtnAddChild_Click(object sender, EventArgs e)
{
Add_Child child = new Add_Child();
child.Show();
}
private void btnRegister_Click_1(object sender, EventArgs e)
{
//create a mother object
Mother m = new Mother();
m.MotherId = int.Parse(txtID.Text);
m.FirstName = txtFname.Text;
m.LastName = txtLname.Text;
m.Mobile = txtMobile.Text;
Giving the new child a reference to its parent object is not the cause of your issue. In summary, you state:
"to have values that will not show up in my label5.text "
This would indicate that it is either your binding that has an issue, you have not implemented INotifyPropertyChanged, or your UI updating mechanism is not working (if you are not using binding). As you haven't stated what you are using for the UI, that is about as much as I can help...
My suggestion, you may use List instead of array, because not all mothers have three children. Example code:
public static class Program
{
static void Main(string[] args)
{
Mother mother = new Mother {
FirstName = "M First", LastName = "M Last", Contact = "225632655"
};
//Add dependents
mother.AddChild(new Child{ChildID = 1, FirstName = "Child FirstName 1", LastName = "Child LastName 1"});
mother.AddChild(new Child{ChildID = 2, FirstName = "Child FirstName 2", LastName = "Child LastName 2"});
mother.AddChild(new Child{ChildID = 3, FirstName = "Child FirstName 3", LastName = "Child LastName 3"});
Console.WriteLine(mother);
//List all the mother dependents
foreach(Child c in mother.Children)
{
Console.WriteLine(c);
}
Console.ReadKey();
}
}
class Mother
{
public string FirstName {get; set;}
public string LastName {get; set;}
public string Contact {get; set;}
private List<Child> _child;
public Mother()
{
_child = new List<Child>();
}
public void AddChild(Child child)
{
_child.Add(child);
}
public List<Child> Children
{
get { return _child; }
}
public override string ToString()
{
return string.Format("{0}, {1} ({2})", LastName, FirstName, Contact);
}
}
class Child
{
public string FirstName {get; set;}
public string LastName {get; set;}
public int ChildID {get; set;}
public override string ToString()
{
return string.Format("{0} {1}, {2}", ChildID, LastName, FirstName);
}
}
I hope, this will help.

Categories

Resources