Let's say I have a class, Person. I also have a button in a WPF window. I want to be able to click that button create a new Person instance (and then add it to a List).
What I don't get is how I do that. My understanding is that I need to specify an instance name (like Person person1 = new Person() - I need to specify that "personsomething" for each instance.
What if I wanted to have a school system with hundreds of people? I can't figure out a way to just click a button and create a new instance for each click (perhaps with some names and stuff, but that's besides the point).
I've got this
private void btnCreatePerson_Click(object sender, RoutedEventArgs e)
{
Person person = new Person(txtFirstName.Text, txtLastName.Text);
personList.Add(person);
ClearTextBoxes();
}
but that only works for a single instance of the class.
I do have to specify a name for each instance, right...?
I do have to specify a name for each instance, right...?
No. By adding the created instance to a list, you're creating one instance per person.
You can read them back from the list by iterating (foreach (var person in personList) { ... }) or querying them (var person = personList.FirstOrDefault(p => p.FirstName = "Joe")).
Related
I'm making a windows forms application and I'm trying to improve my code so I'd like a little bit of advice/help.
I have a list with data at lets say my first form that I add data to from a database. I then pass around one persons details from that list rather than the whole list. My Problem is that I don't think I'm passing around data correctly and I'd like to do it correctly.
Example of what I'm doing (accountholders is of type object?):
Form 2 =I want to pass the data into this form:
private AccountHolders person;
public void SetThePersonsValue(AccountHolders inputAccountHolder)
{
person = inputAccountHolder;
}
Form 1 = I'm taking data from this form, I want to update the list that in this form later on:
WithdrawNoReceipt withdrawNoReceipt = new WithdrawNoReceipt();
withdrawNoReceipt.SetThePersonsValue(person);
withdrawNoReceipt.ShowDialog();
So I want to use a get/set property (?) to do this but I'm not sure how to do so.. Ideally I want the person I'm passing around to be a pointer so the originally list gets updated so I can write the data back to the database without passing the data back to the first form.
If you need any more information please let me know! Thanks in advance.
Are you referring to a property? because then you need to add the following code
private AccountHolders person;
public AccountHolders Person
{
get{return person;}
set{person = value;}
}
the property points to the private member person. Ideally you add a PropertyChanged event in the property so your form knows something has been updated?
EDIT:
For filling the property value, value is of type AccountHolders
public void SetThePersonsValue(AccountHolders inputAccountHolder)
{
//Set the value
Person = inputAccountHolder;
}
WithdrawNoReceipt withdrawNoReceipt = new WithdrawNoReceipt();
//get the value
WithdrawNoReceipt.SetThePersonsValue(Person);
WithdrawNoReceipt.ShowDialog();
while debugging you will now see you person object changes whenever you update your Person object
In my C# winform project I used several user controls.
Here it contain two option like this
Home > Person > Addperson
Home > Teacher > AddTeacher
Person and Teacher contain a listbox which display all person/teachers from database.
when I add person using Addperson, data entered successfully. But when I go back to Person It doesn't show anything. At the same time If I go back to home and enter into AddTeacher option, here from dropdown list I can find that newly added data.
Now if I add that person as a teacher and go back to Teacher it won't show anything but data actually inserted successfully. Then if I close the whole program and reopen than everything show correctly.
All I want is to refresh those usercontrol somehow so that every time any change happens it will show that change instantly without closing down whole program.
I tried different methods but none of them works. I tried refresh method. Also tried
with datasource=null before actual datasource declaration.
Code for person Listbox:
var personListDictionary = new Dictionary<int, string>();
SqlCommand prsonListCmd = new SqlCommand("SQL QUERY", Connection);
SqlDataReader dr = prsonListCmd.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
...
personListDictionary.Add(Key, Value);
}
}
PersonList.DisplayMember = "Value";
PersonList.ValueMember = "Key";
PersonList.DataSource = new BindingSource(personListDictionary, null);
If I understand your example correctly, then you have one Windows form, which contains Person and AddPerson user controls. One option to solve this is to:
Add an OnPersonAdded event in the AddPerson user control:
Add a Refresh method in Person user control (the same code that you posted in your example)
Add a handler for OnPersonAdded in the main Windows form, which refreshes the data in the Person user control.
AddPerson user control:
public event EventHandler<object, EventArgs> OnPersonAdded;
// When you add a Person, then raise the event:
var handler = OnPersonAdded;
if (handler != null)
{
OnPersonAdded(this, EventArgs.Empty);
}
Person user control:
public void Refresh()
{
// your code from the example
}
Parent windows form:
addPersonUserControl.OnPersonAdded += (sender, e) => personUserControl.Refresh();
I have been working on trying to understand ArrayList but I have run into a problem with the final part of my search function.
I have an array list set up to take data in from a StreamReader. The data consists of numerous properties to do with teams, such as their name and the image path to their logo.
I have then created a search that scans through the array list for a specific piece of string input through a textbox by the user.
I have then created an if statement to open up a new form if that search was returned true.
I would like the new form to load up each property of the team according to the data searched for. E.g if I searched for "Liverpool" it would then come up with the manager name, stadium name as well as the searched for name in the new form. I do not know how to do this.
The only tool that I can really think of to do this is the load.event procedure but I can not find a lot of information about linking it to an array list.
private void btn_Search_Click(object sender, EventArgs e)
{
foreach (Object obj in allTeams)
{
Team = (Team)obj;
if (team.teamName.ToUpper() == nameToMatch.ToUpper()) //case insensitive search.
{
FormTeam frmTeam = new FormTeam(Team); //windows form that displays team info.
frmTeam.Visible = true;
break;
}
}
}
above is my search function. (I have not used List<T> because it was required that everything must be stored in an ArrayList.)
Is what I am trying to achieve possible? And if so how?
Also, you may want to use Linq on your ArrayList
foreach(var team in allTeams.OfType<Team>())
{
if(team.TeamName.Equals(nameToMatch, StringComparison.InvariantCultureIgnoreCase))
{
frmTeam = new FormTeam(Team);
Aplication.Run(frmTeam); // or frmTeam.Show();
break;
}
}
Inside the Constructor of your TeamForm class you simply assign all Values from the Team- Object to the fields on the Form.
public FormTeam (Team team)
{
teamName.Text = team.TeamName; // label or something
teamPlayerCount.text = team.PlayerCount.ToString();
...
}
If you need to search on a string such as the teamName, it would be better to use something like a Dictionary<string,Team> rather than an Arraylist. Then you'd be able to do
Team t = dic[nameToMatch.ToUpper()];
where dic is the instance of Dictionary<string,Team> that contains all your teams.
First, you're missing a variable name there. I think you meant
foreach (Object obj in allTeams)
{
Team t = (Team)obj;
if (t.teamName.ToUpper() == nameToMatch.ToUpper()) //case insensitive search.
{
FormTeam frmTeam = new FormTeam(t); //windows form that displays team info.
frmTeam.Visible = true;
break;
}
}
But why not used a typed generic List, not have to do all this silly casting.
But your question is "how can I pass what I searched to the new form", correct? I'd change the constructor for FormTeam to something like FormTeam(Team t, string nameToMatch) and save the value locally in TeamForm so you can do highlighting or whatever.
I have been working with Entity Framework (VS2010 Framework 4.0) in my proyect. I had some trouble with using a different object context per form. What I did then, was to create a object context in the Main Menu Form (stays opened) and everytime I create and show one form, I pass that object context to this new form. Example:
public partial class frm_Menu : Base
{
public Sistema_financiero_Entities db = new Sistema_financiero_Entities();
private void cancelarCuotaToolStripMenuItem_Click(object sender, EventArgs e)
{
frm_Cancelacion_Cuota Form1 = new frm_Cancelacion_Cuota();
Form1.db = db;
Form1.Show();
}
}
Ok, that solution worked fine until now because I needed to use and pass objects throw the differents forms sometimes, and if the objects contexts were different, I got an error.
Now, I have detected a huge issue using it this way. I have a form, where I can pay for the different installments of a loan. I´ll attach an image so then you can see what I´m talking about.
There, you select the different installments you want to pay for. Then, you introduce the value you will finally pay in "Total cobrado". Here is the important thing: When the checkbox image is checked (the blue one - already checked in the image), I create a "payment" entity per installment. Every "payment" object is stored in a list. If I uncheck it, I can change the value and the same thing is done. Obviously, I´m clearing the list before doing a list.Clear();. Then, one the checkbox checked, I can press "Aceptar" (accept). There I add to the database every "payment"(PAGO) in the list. After that, I save all changes.
foreach (Pago p in Lista_nuevos_pagos)
{
db.AddToPago(p);
}
try
{
db.SaveChanges();
this.Close();
}
My problem, is that it´s not only adding those "payments" in the list but the other "payments" entities that were in the list before clearing it. I reach the conclusion that when I clear the list, the objects remains in the object context. I thought that if the entity is not in the database, I have to Add it to the entity in the object context as I did with pago (db.AddToPago(p);).
I wanted to ask you guys how can I solve this issues. I solved it now doing this:
private void cancelarCuotaToolStripMenuItem_Click(object sender, EventArgs e)
{
Sistema_financiero_Entities db = new Sistema_financiero_Entities();
frm_Cancelacion_Cuota Form1 = new frm_Cancelacion_Cuota();
Form1.db = db;
Form1.Show();
}
Instead of creating just one global db for all forms, I create one in the Main Menu for every form. Then, in that form closed event, I dispose that object context.
Then, when i check the checkbox image, before creating the "payments", I delete every "Pago" entity from the object context:
foreach (Pago p in Lista_nuevos_pagos)
{
db.DeleteObject(p);
}
Lista_nuevos_pagos.Clear();
Doing this works correctly, but I´m still having trouble with some other created entities (Installments) that are not deleted when I clear a list. I think I´m doing it wrongly, thats why I need some direction to use EF correctly. I really need to get this done really soon, I don´t have too much time to read EF tutorials.
Just in case, this is how I create every "Pago" (payment)
Pago p = new Pago();
p.desc_aumento_intereses = nudwb1.Value;
p.desc_aumento_punitorios = nudwb2.Value;
p.desc_aumento_gastos = nudwb3.Value;
p.desc_aumento_comision = nudwb4.Value;
p.cotizacion = ntxt_Cotizacion.Value;
p.fecha_hora = fecha_hora;
Cuota c = new Cuota();
string name = tbx.Name.Substring(tbx.Name.IndexOf("-") + 1);
int nro_cuota = Convert.ToInt32(name);
c = Lista_cuotas_cobrar.Where(x => x.num_cuota == nro_cuota).First();
p.Cuota.Add(c);
Thank you for reading, I know this is a lot of info. Hope some guide soon..
I guess that you have references to those object in your Lista_nuevos_pagos list. This is why they will be duplicated.
As a course project i'm building a form in c# which contains two user controls.
The first user control has a checkedlistbox and the second control has also a checkedlistbox when the first control checkedlistbox will contain list of people (male/female) and the second user control the checkedlistbox will have two options: male, female and when I click a button on the first control which says: "update friends" it's suppose to go to the second control and check if we selected male or female and according to that to update the checkedlistbox in the first user control with friends by gender type by what was selected on the second control.
Basically I want to raise an event every time the button on the first control selected then to get the data from the second control to the first control.
Is it possible to do so between two controls who are inside a form and are different controls?
Any help will be appriciated.
Thanks.
To do this "correctly," you would want to use something like the MVC architecture. It's definitely a lot more work initially to understand and implement but is very useful to know if you plan on doing any serious UI application development. Even if you don't go all the way with it, the concepts are useful to help design even "quick and dirty" applications.
Define your data model without thinking in terms of the UI, e.g.:
internal enum Gender
{
Male,
Female
}
internal class Person
{
public Gender Gender { get; set; }
public string Name { get; set; }
}
// . . .
// Populate the list of people
List<Person> allPeople = new List<Person>();
allPeople.Add(new Person() { Gender = Gender.Male, Name = "Xxx Yyy" });
allPeople.Add(new Person() { Gender = Gender.Female, Name = "Www Zzz" });
// . . .
For the view portion, you would typically use data binding on the UI controls so that the controls will automically reflect changes to the underlying data. However, this can get difficult especially if you are not using a database-like model (e.g. System.Data.DataSet). You may opt to "manually" update the data in the controls which might be fine in a small app.
The controller is the portion that uses the UI events and makes changes to the model, which may then be reflected as changes in the view.
internal class Controller
{
private Gender selectedGender;
private List<Person> allPeople;
private List<Person> friends;
public Controller(IEnumerable<Person> allPeople)
{
this.allPeople = new List<Person>(allPeople);
this.friends = new List<Person>();
}
public void BindData(/* control here */)
{
// Code would go here to set up the data binding between
// the friends list and the list box control
}
// Event subscriber for CheckedListBox.SelectedIndexChanged
public void OnGenderSelected(object sender, EventArgs e)
{
CheckedListBox listBox = (CheckedListBox)sender;
this.selectedGender = /* get selected gender from list box here */;
}
// Event subscriber for Button.Click
public void OnUpdateFriends(object sender, EventArgs e)
{
this.friends.AddRange(
from p in this.allPeople
where p.Gender == this.selectedGender
select p);
// If you use data binding, you would need to ensure a
// data update event is raised to inform the control
// that it needs to update its view.
}
}
// . . .
// On initialization, you'll need to set up the event handlers, etc.
updateFriendsButton.Click += controller.OnUpdateFriends;
genderCheckedListBox.SelectedIndexChanged += controller.OnGenderSelected;
controller.BindData(friendsListBox);
// . . .
Basically, I recommend not having controls talk directly, but rather through a controller-like class as above which has knowledge of the data model and the other controls in the view.
Of course it's possible: you need to make the link between the 2 controls in the form.
Just declare an event 'ButtonClicked' in control #1
Then make a public method 'PerformsClick' on the control #2
And in the form, in the constructor, after the call to InitializeComponent, link the event from the control #1 to the method to the control #2:
control1.ButtonClicked += delegate(sender, e) {
control2.PerformsClick();
};
(I type on the fly to give you an idea, it'll surely not compile)
If you want to pass any data, just add parameters in the PerformsClick method.