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.
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 setting up a User and Admin Permissions which works perfectly well but I want to disable some ToolStripMenuItem from "Users" but Enable them only for "Admin".
Here's the code that logs User and Admin in depending on their Roles.
if (dt.Rows[0][0].ToString() == "1")
{
if (ComboBox_LoginAs.SelectedIndex == 0)
{
this.Hide();
Main_Form mainSystem = new Main_Form();
mainSystem.Show();
}
else if (ComboBox_LoginAs.SelectedIndex == 1)
{
this.Hide();
Main_Form mainSystem = new Main_Form();
mainSystem.Show();
/* disable View All Employees for Users */
ViewAllEmployeesToolStripMenuItem.Enable = false;
}
I expect the Users to not be able to view all Employee Records except the Admin.
I hope this question will not get down voted.
Thank you for your help!!
Here is an example of an interface I used once that accomplishes something similar.
Main
namespace UnNamed Project
{
class Program
{
static void Main(string[] args)
{
User user;
user = new SuperUser("Bob", "12345");
if (user.Login())
{
Console.WriteLine($"Welcome {user.Name}");
}
else
{
Console.WriteLine("An error has occured.");
}
Utility.PauseBeforeContinuing();
}
}
}
Interface Class
namespace UnNamed Project
{
interface ILoginHandler
{
bool HandleLogin();
void SetPassword(string password);
}
}
User Class
namespace UnNamed Project
{
abstract class User
{
private string _name;
private int _securityLevel;
public User(string name, int securityLevel)
{
_name = name;
_securityLevel = securityLevel;
}
abstract public bool Login();
}
}
SuperUser Class
namespace UnNamed Project
{
class SuperUser : User
{
private ILoginHandler _loginHandler;
public SuperUser(string name, string password) : base(name, 10)
{
_loginHandler = new FaceLogin(password);
}
public override bool Login()
{
return _loginHandler.HandleLogin();
}
}
}
As you can see, if setup properly you can create an object "User" and another object "Admin" and then create an abstract method within user. You can alternatively do a virtual method to handle the login, just make sure that your admin class has an override for it's own Login() method. This will cause the program to use the method directly related to the object.
Okay, so I tried changing my MenuStripItem Modifier state to "public". Then I created an object on my main form.
public static Main_Form GetMainForm_Obj;
public Main_Form()
{
InitializeComponent();
}
Then inside my Form Load, I added:
private void Main_Form_Load(object sender, EventArgs e)
{
eMPLOYEESToolStripMenuItem.Enabled = true;
GetMainForm_Obj = this;
}
And finally, in my Login form:
if (ComboBox_LoginAs.SelectedIndex == 0)
{
this.Hide();
Main_Form mainSystem = new Main_Form();
mainSystem.Show();
}
else if (ComboBox_LoginAs.SelectedIndex == 1)
{
this.Hide();
Main_Form mainSystem = new Main_Form();
mainSystem.Show();
Main_Form.GetMainForm_Obj.eMPLOYEESToolStripMenuItem.Enabled = false;
}
Thank you everyone!
I just learned how to pass arguments into methods, so I'm refactoring my code to make it cleaner. I have created a new "ValidateInput" class which holds a ValidateFinancialsInput method which I pass a string into. It then checks the string to see if it is correct, if it's not I want to show a messageBox, then stop execution of ALL of the code. If i use "return;", it just resumes execution of the Parent method. How do I stop execution of all of the code within the ValidateFinancialsInput method? I tried researching this for a while to no avail. Here is my code:
Class Parent
{
private void button2_Click(object sender, EventArgs e)
{ var CompanyVar = comboBox1.Text;
ValidateInput vi = new ValidateInput();
vi.ValidateFinancialsInput(CompanyVar);
//the rest of my code for the application is here
//the rest ...
//the rest...
}
}
class ValidateInput
{
public void ValidateFinancialsInput(string Co)
{
string[] validCompany = { "BVV", "LWDO" };
if (validCompany.Contains(Co) == false)
{
MessageBox.Show("You have entered an invalid company.");
//what do I put here to stop all code execution?
}
}
}
You should try and use return values state intent to calling methods
Class Parent
{
private void button2_Click(object sender, EventArgs e)
{ var CompanyVar = comboBox1.Text;
ValidateInput vi = new ValidateInput();
if(!vi.ValidateFinancialsInput(CompanyVar))
{
MessageBox.Show("You have entered an invalid company.");
return;
}
//the rest of my code for the application is here
//the rest ...
//the rest...
}
}
class ValidateInput
{
public bool ValidateFinancialsInput(string Co)
{
string[] validCompany = { "BVV", "LWDO" };
if (validCompany.Contains(Co) == false)
{
return false;
}
return true;
}
}
What I'm doing here is returning a true|false value to indicate whether the validation has passed, if it has not passed then I display the MessageBox, else it continues the execution of the "other" code.
Hope this helps
The simplest way is with an exception:
class Parent
{
private void button2_Click(object sender, EventArgs e)
{
try
{
var CompanyVar = comboBox1.Text;
ValidateInput vi = new ValidateInput();
vi.ValidateFinancialsInput(CompanyVar);
//the rest of my code for the application is here
//the rest ...
//the rest...
}
catch (ValidationException ex)
{
MessageBox.Show(ex.Message);
}
}
}
class ValidationException : Exception
{
public ValidationException(string message) : base(message)
{
}
}
class ValidateInput
{
public void ValidateFinancialsInput(string Co)
{
string[] validCompany = { "BVV", "LWDO" };
if (validCompany.Contains(Co) == false)
{
throw new ValidationException("You have entered an invalid company.");
}
}
}
This will stop execution of ValidateFinancialsInput and in button2_Click move execution inside the catch (ValidationException ex) where you can decide what to do with the validation error
You have a class that it's whole purpose is to validate, So you could add a public method IsValidated
You could add much more with the class, for example have a list of all business rules it violates and return them through another method or property.
class ValidateInput
{
public bool IsValidated {get; private set}
public bool ValidateFinancialsInput(string Co)
{
string[] validCompany = { "BVV", "LWDO" };
this.IsValidated = validCompany.Contains(Co)
}
}
This class should only know about the validation process and should do nothing else.
You have a few options. It looks like you have buttons in your program so I would guess this is not a console application. If you want the application to completely stop you can use Application.Exit or check out Environment.Exit https://msdn.microsoft.com/en-us/library/system.environment.exit(v=vs.110).aspx
However, I would suggest using exceptions so you do not terminate your entire program:
try
{
var CompanyVar = comboBox1.Text;
ValidateInput vi = new ValidateInput();
vi.ValidateFinancialsInput(CompanyVar);
//the rest of my code for the application is here
//the rest ...
//the rest...
}
catch (ValidationException ex)
{
MessageBox.Show(ex.Message);
}
}
public void ValidateFinancialsInput(string Co)
{
string[] validCompany = { "BVV", "LWDO" };
if (validCompany.Contains(Co) == false)
{
throw new ValidationException("You have entered an invalid company.");
}
}
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.
}
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.