public class Account
{
public string Username
{
get { return Username; }
set { Username = value; }
}
}
public class ListAcc
{
static void Data()
{
List<Account> UserList = new List<Account>();
//example of adding user account
Account acc = new Account();
acc.Username = textBox1.Text; //error
UserList.Add(acc);
}
}
there are a error from access to textBox1.Text? ( An object reference is required for the nonstatic field, method, or property)... Someone can help?
but if the code is:
private void textBox1_TextChanged(object sender, EventArgs e)
{
List<Account> UserList = new List<Account>();
//example of adding user account
Account acc = new Account();
acc.Username = textBox1.Text;
UserList.Add(acc);
}
it's work! someone can help me fix my error? Many thanks!
TextBox1 is a member variable which cannot be accessed in a static method.
You can have your code as below.
public class ListAcc
{
private static List<Account> UserList;
public static List<Account> Data()
{
return UserList;
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
UserList = new List<Account>();
//example of adding user account
Account acc = new Account();
acc.Username = textBox1.Text;
UserList.Add(acc);
}
Notice that the Data method is static and textBox1_TextChanged is not. textBox1 is an instance variable, it belongs to a specific instance of your class. static methods belong to the class itself and cannot see instance variables. static methods would not know which instance to talk to.
Why do you want the Data method to be static?
You can't access a field/property/method of an object (in this case textBox1 from the container object e.g a WinForm object) from a static method without using a reference to the object e.g form1.TextBox1. TextBox1 is also probably private inside your container object e.g form1 so you won't be able to access it outside the form1 object in your ListAcc object either.
Below is some sample code that should work.
public class ListAcc
{
// Don't put this in Data or you'll recreate it again and
// again when you call Data
private static List<Account> UserList = new List<Account>();
// We'll pass in textBox1.Text via name parameter instead of
// referencing it directly which we can't
public static void Data(string name)
{
//example of adding user account
Account acc = new Account();
acc.Username = name;
UserList.Add(acc);
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
// We'll call Data and pass in textBox1.Text as our UserName
ListAcc.Data(textBox1.Text);
}
Note that TextChanged event is not exactly the best place to put your Data method because it is raised everytime you enter a new character/press backspace/etc.
textBox1 is object variable which belong to object, so you need to create object (instance of) of ListAcc class before you use it.
void Data() is static method which belong to class not object, this mean you can use them without create instance of it.
From your source code you try to use textBox1 (which must belong to object) inside static method and this is unreasonable to do. You can solve this problem by remove static keyword or remove textBox1 from this method.
Related
I am making a very basic sort of online ATM app using c#.NET. Bascically i have made a class called account and have used a constructor to store the accounts of customers, making them objects of the class. These customers are to enter a pin to login. The customer's pin is one of the parameter of the customer object and i have been trying to make a loop that will loop through all the individual customers and identify which account the pin belongs to.
class Account
{
public string customerName;
public string pin;
public int balance;
public Account(string accCustomerName, string accPin, int accBalance)
{
customerName = accCustomerName;
pin = accPin;
balance = accBalance;
}
}
private void Form1_Load(object sender, EventArgs e)
{
Account acc1 = new Account("Henry_Adobe", "2316", 10000);
Account acc2 = new Account("Patrick_Boka", "3198", 15000);
Account acc3 = new Account("Fred_Simp", "8768", 20000);
Account acc4 = new Account("Derek_Black", "7645", 25000);
if (txtInput.Text == acc1.pin)
{
MessageBox.Show("Login Succesful!");
}
}
I have managed to access the pin by stating the name of a specific name of each object(acc1.pin) but this is not efficient as it requires me to enter the name of very object. Is there a way in which i could easily access the parameters of all the accounts?
I'll take a you a step further, since an ATM app that forgets the last balance each time it runs isn't very useful.
Let's start with Account class:
class Account
{
public string CustomerName {get;set;};
public string PIN {get;set;};
public decimal Balance {get;set;};
public Account(string customerName, string Pin, decimal balance)
{
CustomerName = customerName;
PIN = Pin;
Balance = balance;
}
public static IList<Account> Accounts {get;private set;} = new List<Account>();
public static void ReadAccounts(string fileName)
{
using var rdr = new Microsoft.VisualBasic.FileIO.TextFieldParser(AccountsFileName))
{
rdr.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited;
rdr.Delimiters = new string[] {','};
Accounts.Clear();
string[] row = null;
while( (row = rdr.ReadFields()) != null)
{
Accounts.Add(new Account(row[3], row[0], Decimal.Parse(row[1])));
}
}
}
public static void WriteAccounts(string fileName)
{
using (var writer = new StreamWriter(fileName, false))
{
writer.WriteLine("PIN,Balance,CustomerName");
foreach(var acct in Accounts)
{
writer.WriteLine($"{acct.PIN},{acct.Balance},\"{acct.CustomerName}\"");
}
}
}
}
We updated the fields to become properties with meaningful data types, added a static place to the keep the list of accounts, and added methods to read and write from a file. Later on, you'll replace the csv file with a database of some kind, but this will get you started.
Now let's move on to loading the form:
private string AccountsFileName = "AccountsFile.csv";
private void Form1_Load(object sender, EventArgs e)
{
Account.ReadFile(AccountsFileName);
}
But we need to stop there. At the point where a form loads, the user hasn't had a chance to enter any text yet! You need a button, in addition to the textbox, where the user can click to login after they type the pin:
private Account currentAccount = null;
private void btnLogin_Click(object sender, EventArgs e)
{
currentAccount = Account.Accounts.FirstOrDefault(a => a.PIN == txtInput.Text);
if (currentAccount != null)
{
MessageBox.Show("Login successful!");
return;
}
MessageBox.Show("Login failed");
}
And, finally, you need a way to save the file when the program ends. For now I'll just use the Form1_Closing event, but later you'll probably need something different:
private void Form1_Closing(object sender, EventArgs e)
{
Account.WriteAccounts(AccountsFileName);
}
What you're still missing is the ability to show users their balance and allow them to make deposits and withdrawals. Additionally, any ATM worth using will need to show individual transactions, typically stored as two off-setting ledger entries.
I'm currently unable to pass a variable from one class to another. My first class is the default made from my form named (Calculator). The second called record.
public void toolStripLabel1_Click(object sender, EventArgs e)
{
Record rec = new Record();
System.Windows.Forms.MessageBox.Show(calculation);
rec.startRecording();
}
The above when I click the the correct variable is displayed in the pop-up box.
namespace CalculatorV2
{
class Record
{
public void startRecording()
{
Calculator calc = new Calculator();
System.Windows.Forms.MessageBox.Show(calc.calculation);
using (StreamWriter writer =
new StreamWriter("important.txt"))
{
writer.WriteLine("Line one");
writer.WriteLine(calc.calculation);
writer.WriteLine("Line Two");
}
}
}
}
But when I call the method startRecording() the variable value is not pulled. Is this because a new class object of calculator is created in which the variable calculation is blank ? Any help would be appreciated.
Pass the instance of class to the method as parameter
class Record
{
public void startRecording(Calculator calculator)
{
System.Windows.Forms.MessageBox.Show(calculator.calculation);
using (StreamWriter writer =
new StreamWriter("important.txt"))
{
writer.WriteLine("Line one");
writer.WriteLine(calculator.calculation);
writer.WriteLine("Line Two");
}
}
}
public void toolStripLabel1_Click(object sender, EventArgs e)
{
Record rec = new Record();
System.Windows.Forms.MessageBox.Show(calculation);
rec.startRecording(this);
}
Modify your method StartRecording() to take calculation as parameter and pass the calculation as argument
rec.startRecording(calculation);
public void startRecording(calculation_VariableType calculation) {}
Instead of passing hole class just pass the class property as you are using only calculation property in your method.
So what i have is basically this:
public partial class ShowList : UserControl
{
public int count;
private static LoadMovies lm = new LoadMovies();
public List<Movie> movieList = lm.GetMovieList();
public ShowList(string genreTitel)
{
InitializeComponent();
......
......
Load(genreTitel)
}
public void Load(string genreTitel)
{
lm.ReadMoviesToList();
string picturepath = Environment.CurrentDirectory + #"\Pictures" + #"\Pictures\";
IEnumerable<Movie> genreMovieList =
movieList.Where(m => m.MovieGenres.Contains(genreTitel) && m.MovieNumberOfRatings > 80).Take(20);
Movie movie1 = genreMovieList.ElementAt(count);
label29.Text = movie1.MovieName;
pictureBox9.Image = Image.FromFile(picturepath + movie1.MovieId + ".jpg");
label24.Text = "Rating: " + Math.Round(movie1.MovieAverageRating, 2);
}
private void Btn_Click(object sender, EventArgs e)
{
count++;
//HERE I NEED SOME CODE TO RELOAD LOAD-METHOD.
}
What i have tried, is to just write Load(); but as the method needs the genreTitel. And i cant reach the genreTitel.
How do i increment count, and reload Load(genreTitel) when clicking on button?
Save genreTitel (title?) to a private variable. In the constructor assign the passed in to the new private variable, then you can access it from the Btn_Click.
Declare a string genreTitel (or name it whatever you want) under your movielist declaration and then before you call Load(genreTitel) the first time in the constructor, do:
this.genreTitel = genreTitel.
This way you have a genreTitle variable accessible to the rest of the class
Assuming you're getting genreTitel from some form field, you can access that field in your Click Event Handler.
Ergo, where you tried to put simply Load(), use Load(formField.Text).
Edit: Just noticed that ShowList(string genreTitel) was a constructor, not a method.
In that case, instantiate a private variable and assign genreTitel to it in your constructor.
do like this
//declare the class level variable like this
private string mgenretitle;
public ShowList(string genreTitel)
{
// initialize the variable over here like this
mgenretitle = genreTitel;
InitializeComponent();
......
......
Load(genreTitel)
}
and then use it over here
private void Btn_Click(object sender, EventArgs e)
{
count++;
// call your load method over here
Load(mgenretitle);
//HERE I NEED SOME CODE TO RELOAD LOAD-METHOD.
}
I have a class called currentUser and another called game. from game, i am trying to access a variable from currentUser, I know for sure that the variable is created and it contains something in currentUser before i call it in game but i get an empty string. What am i doing wrong here. here is what i have
public class currentUser
{
private string currentUser;
public string getCurrentUser
{
get {return currentUser;}
set {currentUser = value;}
}
//this gets pushed in the beginning of the program
private void btn_click(object sender, RoutedEventArgs e)
{
currentUser = txtUsername.Text;
}
}
public class game
{
currentUser myCurrentUser = new currentUser();
string var = myCurrentUser.getCurrentUser();
//this is another method being called in another class, but i dont think it is relevant. by the time i step over to here, var is null.
clsScores.getScore(25, var);
}
i have tried looking, but this is the same example i see, so i don't know why it would not be working.
Try this: (I don't know how you are calling the code in Game, so I've just called it in a method DoSomething). If you get the result "No name", that means there's a problem with getting the user from the textbox.
public class CurrentUser
{
private string _user;
public string User
{
get { return _user; }
set { _user = value; }
}
//this gets pushed in the beginning of the program
private void btn_click(object sender, RoutedEventArgs e)
{
if(String.IsNullOrEmpty(txtUsername.Text)
{
_user = "No name";
}
else
{
_user= txtUsername.Text;
}
}
}
public class Game
{
public void DoSomething()
{
var myCurrentUser = new CurrentUser();
var user = myCurrentUser.User;
Console.WriteLine(user);
}
}
You have accidentally put parenthesis in:
string var = myCurrentUser.getCurrentUser();
Remove them because "getCurrentUser" is a property, not a method. Properties do not need parenthesis.
Ontop of a lot of other problems mentioned unless you are setting "currentUser" in the time between "currentUser myCurrentUser = new currentUser();" and "string var = myCurrentUser.getCurrentUser();". Your variable will never get set.
Im new to .net and this is also my first post here so apologies in advance for any newb mistakes I may be doing:)
Background of the problem.
I’m working on a C# project and as part of it I have to store windows form data onto a database. I am using a data class “person” to transport the windows form data to a class responsible for accessing the database on the windows forms behalf. I wish to use the Singleton pattern on the windows forms code to prevent multiple instances of the window from existing.
Problem
In the save buttons event handling code I wish to create a “Person” object, populate it with user entered values and send it to be saved onto the database. The problem occurs here. The “Person” object does not get populated!
I’ve tried doing this in another form where I have not modified the code to accommodate the singleton pattern and that works.
So what am I doing wrong here? Is there a way for me to still keep the singleton pattern and make it work?
Window Form Code
namespace AgTrain
{
public partial class CreateAdmin : Form
{
private static CreateAdmin instance;
private CreateAdmin()
{
InitializeComponent();
}
private void CreateAdmin_Load(object sender, EventArgs e)
{
}
public static CreateAdmin getInstance()
{
if(instance==null)
{
instance = new CreateAdmin();
instance.InitializeComponent();
}
return instance;
}
public void makeInstanceNull()
{
instance = null;
}
private void button1_Click(object sender, EventArgs e)
{
Person personToBeSaved = new Person();
PersonDAO personDAO = new PersonDAO();
personToBeSaved.FirstName = textBox1.Text;
personToBeSaved.LastName = textBox2.Text;
personToBeSaved.Address = textBox3.Text;
personToBeSaved.TelNo = textBox4.Text;
personToBeSaved.UserName = textBox5.Text;
personToBeSaved.Password = textBox6.Text;
personToBeSaved.UserType = "admin";
personDAO.addPerson(personToBeSaved);
}
}
}
Caller Code
private void createAdminToolStripMenuItem_Click(object sender, EventArgs e)
{
CreateAdmin creAdmin = CreateAdmin.getInstance();
creAdmin.Closed += (s, ex) => { creAdmin.makeInstanceNull(); };
creAdmin.MdiParent=this;
creAdmin.Show();
}
Thanks.
Dumidu
You are calling InitializeComponent twice.
Try that:
private static CreateAdmin _instance;
public static CreateAdmin Instance
{
get { return _instance ?? (_instance = new CreateAdmin()); }
}
In my opionion is thefiloe's solution the cleanest, but there is a further possibility to introduce (effective) singletons in C#:
public static readonly CreateAdmin Instance = new CreateAdmin();
Client Code:
CreateAdmin.Instance.DoSomething()
But as already mentioned I recommend thefiloe's way!