Instance of List mess upp values - c#

I've a list in a class:
public class LogInList
{
public int AnsNr { get; set; }
public List<LogInList> GetNr()
{
List<LogInList> Nr = new List<LogInList>();
Nr.Add(new LogInList { AnsNr = 101 });
return Nr;
}
}
And I've created a instance of it in my Login form:
public partial class LogIn : Form
{
LogInList Log = new LogInList();
AND in my button in the form I've the following code:
private void button1_Click(object sender, EventArgs e)
{
if (inMatningTextBox.Text == Log.AnsNr.ToString())
{
Ö.ShowDialog();
this.Close();
}
else
{
MessageBox.Show("Du har skrivit in fel anställningsnummer!");
}
The thing is, the int value of 'AnsNr' is automatically changed from 101 to 0 when the program starts. I guess that the new Instance is responsible for this? It tracks back to how many Items there is in the list, I guess? How do I go around this? I want to be able to enter '101' to login.. not 0 ;)
Many thanks!

In your code, you are never calling the GetNr method of LogInList, but access the member AnsNr which is (implicitly) initialized with 0.
Perhaps you can achieve your goal using
if ( Log.GetNr().Select( entry => entry.AnsNr ).Contains( Convert.ToInt32( inMatningTextBox.Text ) ) )
{
Ö.ShowDialog();
this.Close();
}
where you would also have to use
include System.Linq;

When you create your form you have this code:
LogInList Log = new LogInList();
It simply creates an instance of LogInList and does not set the value of AnsNr.
Your code doesn't show a call to GetNr, but if it is called there is a second instance of LogInList created and that one does set the value of AnNr to 101.
The first instance value of AnsNr is never set, that's the problem with your code.

Related

Passing a variable between forms WINFORMS [duplicate]

Wierd behaviour when passing values to and from second form.
ParameterForm pf = new ParameterForm(testString);
works
ParameterForm pf = new ParameterForm();
pf.testString="test";
doesn't (testString defined as public string)
maybe i'm missing something? Anyway I'd like to make 2nd variant work properly, as for now - it returns null object reference error.
Thanks for help.
Posting more code here:
calling
Button ParametersButton = new Button();
ParametersButton.Click += delegate
{
ParameterForm pf = new ParameterForm(doc.GetElementById(ParametersButton.Tag.ToString()));
pf.ShowDialog(this);
pf.test = "test";
pf.Submit += new ParameterForm.ParameterSubmitResult(pf_Submit);
};
definition and use
public partial class ParameterForm : Form
{
public string test;
public XmlElement node;
public delegate void ParameterSubmitResult(object sender, XmlElement e);
public event ParameterSubmitResult Submit;
public void SubmitButton_Click(object sender, EventArgs e)
{
Submit(this,this.node);
Debug.WriteLine(test);
}
}
result:
Submit - null object reference
test - null object reference
pf.ShowDialog(this); is a blocking call, so pf.Submit += new ParameterForm.ParameterSubmitResult(pf_Submit); is never reached: switch the order.
Submit(this,this.node); throws a null object reference because no event is assigned to it (see above). Generally, you should always check first: if (Submit != null) Submit(this,this.node);
You should change ``pf.ShowDialog(this);topf.Show(this);` so that your main form isn't disabled while your dialog box is open, if that's what you want, or use the model below (typical for dialog boxes.)
I'm not sure what pf_Submit is supposed to do, so this might not be the best way to go about it in your application, but it's how general "Proceed? Yes/No" questions work.
Button ParametersButton = new Button();
ParametersButton.Click += delegate
{
ParameterForm pf = new ParameterForm(testString);
pf.ShowDialog(this); // Blocks until user submits
// Do whatever pf_Submit did here.
};
public partial class ParameterForm : Form
{
public string test; // Generally, encapsulate these
public XmlElement node; // in properties
public void SubmitButton_Click(object sender, EventArgs e)
{
Debug.WriteLine(test);
this.Close(); // Returns from ShowDialog()
}
}
When you want to use your second variant, you have to use a getString()-Method, where you can put the e.g. "testString". The way you wrote it, "testString" should be a method (and got brackets).
EDIT (a bit more precise):
You could write:
pf.getString(testString);
, if "pf" is an instance of your own class, otherwise you had to look up, whether you can retrieve a String in this class.
the thing was in line order :)
pf.Submit += new ParameterForm.ParameterSubmitResult(pf_Submit);
and
pf.Test = "test";
should have been set before
pf.ShowDialog(this);
my mistake thingking that parameter can be passed after 2nd form was displayed
thnx for answers

Property Data Not Outputing to Controls

In one of my current projects, I have been attempting to develop a system that will take data input from textboxes on one form, and input them into a list on another form so that they may be displayed via a listbox and labels on another form as a data reference for manual input into a database.
//Create Attendance Report Instance
AttendanceReport report = new AttendanceReport();
private void inputButton_Click(object sender, EventArgs e)
{
try
{
//Declare Variables
string administratorVerify = verificationBox.Text;
//Inputs Change Based on NewStudent Check
if (passwordInput.Text == passwordTextBox.Text)
{
//Save Changes
Save();
}
Relevant Section => else if (newStudentCheck.Checked == true)
{
//New Verification Instance
VerificationClass verify = new VerificationClass();
//Verification Gateway
if (verify.Verify(administratorVerify) == true)
{
//Send Student to Attendance Report List
report.DisplayStudent();
}
else
{
MessageBox.Show("Unauthorized Password\nOnly Authorized Administrators May Access this Function");
}
}
//Clear Inputs
clearInputs();
}
I designed the part of the program that retrieves the data and displays it to function off of an universal instance of the second form, calling an instance of the first form to retrieve the data. I originally had the program create a new instance of the second form whenever the input button was clicked, before I moved the instantiation out of that block, making it a universal instance.
List<NewStudent> studentList = new List<NewStudent>();
private void RetrieveStudentInfo(NewStudent student)
{
//Temp Variables
int ID;
int Grade;
//Create MainForm Instance
MainForm reference = new MainForm();
//Get Values
student.Class = reference.classBox.Text;
student.Name = reference.nameBox.Text;
if (int.TryParse(reference.idBox.Text, out ID))
{
student.ID = ID;
}
else
{
MessageBox.Show("Invalid ID");
}
student.Password = reference.createPasswordBox.Text;
student.District = reference.districtBox.Text;
student.Country = reference.countryBox.Text;
if (int.TryParse(reference.gradeBox.Text, out Grade))
{
student.Grade = Grade;
}
else
{
MessageBox.Show("Invalid Grade");
}
}
public void DisplayStudent()
{
//Create Object
NewStudent student = new NewStudent();
//Get Student Info
RetrieveStudentInfo(student);
//Add Object to List
studentList.Add(student);
//Add Entry to Selection
newStudentSelection.Items.Add(student.ID);
}
private void newStudentSelection_SelectedIndexChanged(object sender, EventArgs e)
{
//Get Selected Item
int index = newStudentSelection.SelectedIndex;
//Display Data
classOutput.Text = studentList[index].Class;
nameOutput.Text = studentList[index].Name;
idOutput.Text = studentList[index].ID.ToString();
passwordOutput.Text = studentList[index].Password;
districtOutput.Text = studentList[index].District;
gradeOutput.Text = studentList[index].Grade.ToString();
countryOutput.Text = studentList[index].Country;
}
For all my life, from where I stand it seems like this program should work. I Intellisense is giving me no styntax errors, and I have attempted to review my logic with fellow amateur programmers in person, but for what ever reason, the data will not output to the controls on the second form. The only I can think of is that somehow by reference variables I pass as arguments to my RetrieveStudentInfo method and such are not actually getting passed somehow, but that shouldn't be correct.
Any advice on this situation would be greatly appreciated.

Why do these two List<string> always contain the same number of items?

I have a very simple program that for some reason has me stumped. I put it down, came back at it again this morning and I'm still stumped. First off, I'm aware this is not an ideal solution. I have two forms: Main and Log. The Main form has a button that adds to List _debugLog when clicked. When btnDebug is clicked, it opens the Log form, passing _debugLog to it. Everything is fine, the timer is setup and runs, everything is normal. The event log.UpdateLog() is triggered every 2.5 seconds to update the Log form with the updated log. However, mainFormLog.Count and _log.Count are always the same and they BOTH increase when btnAdd is clicked on the main form. How does _log have the new _debugLog (mainFormLog) from the tick event?
namespace Tool
{
public partial class Main : Form
{
private List<string> _debugLog = new List<string>();
public Main()
{
InitializeComponent();
}
private void btnAdd_Click(object sender, EventArgs e)
{
_debugLog.Add("message!");
}
private void btnDebug_Click(object sender, EventArgs e)
{
Log log = new Log(_debugLog);
log.Show();
Timer dt = new Timer();
dt.Interval = 2500;
dt.Enabled = true;
dt.Tick += delegate {
log.UpdateLog(_debugLog);
};
}
}
public partial class Log : Form
{
private List<string> _log;
public Log(List<string> log)
{
InitializeComponent();
_log = log;
}
public void UpdateLog(List<string> mainFormLog)
{
if (mainFormLog.Count > _log.Count)
{
MessageBox.Show("Log has been updated!");
}
else
{
MessageBox.Show("Nothing new!" + mainFormLog.Count.ToString() + " / " + _log.Count.ToString());
}
}
}
}
Well, you're passing the reference to the list from Main to Log, so it's actually the same list.
If you want a separate list that gets initialized with the list from Main you can use:
public Log(List<string> log)
{
InitializeComponent();
_log = new List<string>(log);
}
Maybe this helps to understand the difference between variables and references:
For a value type, the value is the information itself. For a reference
type, the value is a reference which may be null or may be a way of
navigating to an object containing the information.
For example, think of a variable as like a piece of paper. It could
have the value "5" or "false" written on it, but it couldn't have my
house... it would have to have directions to my house. Those
directions are the equivalent of a reference. In particular, two
people could have different pieces of paper containing the same
directions to my house - and if one person followed those directions
and painted my house red, then the second person would see that change
too. If they both just had separate pictures of my house on the paper,
then one person colouring their paper wouldn't change the other
person's paper at all.
All your variables _debugLog, mainFormLog, and _log are pointing to the same list in memory. You've only created one list, and when you assign a new variable to that list, it's just a pointer to some location in memory, it doesn't automatically create a new copy of the list.

How to add/remove items from a list from a different form?

Say I have a list called listOfFruits in my main form. In a second form I've made I want the user to be able to remove items from that list to a second list called removedFruits. Currently I know I can access these lists in my second form simply passing them as parameters in the form constructor. However c# can't do pointers (correct?) so how can I effect the main form's copy of these lists from my second form? Because currently any changes to those lists in my second form don't effect the main form's original copy of the lists. If I were to remove 5 fruits from the listOfFruits passed to my second form then after finishing my work the main form would still still have a full listOfFruits and an empty removedFruits. Is there a simple fix to this? Maybe a get/set or a way to add/remove items from the original lists from the second form? Maybe the answer is in some sort of accessor stuff?
EDIT: To clarify; I want to add to one list, and remove from another. Not add/remove to the same list. Not sure if this matters entirely but I figured I'd be specific here in case it does.
EDIT2: I think the issue is I'm copying the original list from the first form and not editing it directly. Can someone fix my code so I can access the original list from my second form instead of making a copy of the list?
public partial class ListSelector : Form
{
private string windowName = Form1.typeOfModuleAdded;
public List<IOModule> innerIOList;
IOModule cardAdded = null;
public ListSelector(List<IOModule> cardList)
{
this.Text = windowName;
innerIOList = cardList;
InitializeComponent();
InitializeList();
}
private void InitializeList()
{
if (windowName == "Drive")
{
string[] listDrives = { "ACS880", "test" };
listBox1.Items.AddRange(listDrives);
}
else if (windowName == "IOBlock")
{
if (!innerIOList.Any())
{
MessageBox.Show("No cards loaded! Please import cards from IO List.", "Error Empty Data", MessageBoxButtons.OK, MessageBoxIcon.Error);
this.Close();
}
foreach (IOModule card in innerIOList)
{
cardAdded = card;
listBox1.Items.Add(card.name);
}
}
else if (windowName == "Local Card")
{
string[] listLocals = { "1756-EN2T", "test" };
listBox1.Items.AddRange(listLocals);
}
else if (windowName == "Processor")
{
string[] listProcessors = { "1756-L71S", "test" };
listBox1.Items.AddRange(listProcessors);
}
}
private void addBtn_Click(object sender, EventArgs e)
{
if (listBox1.SelectedItem != null)
{
Form1.SetModule(listBox1.SelectedItem.ToString());
Form1.confirmedAdd = true;
this.Close();
}
else if (cardAdded != null)
{
innerIOList.Remove(cardAdded);
}
else
{
MessageBox.Show("No module selected!");
}
}
and here's how I pass the list to that form from my first form:
ListSelector test = new ListSelector(ioList);
test.ShowDialog();
where ListSelector is the name of my second form, and ioList is the list im passing to it.
EDIT3: added more code
"However c# can't do pointers (correct?) so how can I effect the main form's copy of these lists from my second form?"
No, not correct. Any object reference (for instance, of a List<Fruit>) is still very much a pointer to a place in memory, and if you pass the same List<Fruit> object to both Forms, they share the same List.
I don't know why your changes to your listOfFruits don't chow up in your first Form. I would check the following things:
Are you 100% sure you use the same List<Fruit> object in both Forms. (If you create a new List like this: new List<Fruit>(listOfFruits) it is NOT the same List)
Does the first Form have any way of finding out, that the List has changed? Possible using a Timer with recurring checks, or (my favorite) triggering an event when you change something, and subscribe an EventHandler in the first Form to the event.
I assume that you have created a second list in your second form that is filled with the items of the first form's list. Then changes on the second list aren't reflected in the first list. You have to use the same reference of the list.
public Form2(List<Fruit> listOfFruits)
{
this._listOfFruits = listOfFruits;
}
private List<Fruit> _listOfFruits;
Instead using a public field, try to use property and on creating your new ListSelector pass the list to the property.
public partial class ListSelector : Form
{
private string windowName = Form1.typeOfModuleAdded;
private List<IOModule> innerIOList;
IOModule cardAdded = null;
public List<IOModule> CardList
{
get
{
return innerIOList;
}
set
{
innerIOList = value;
InitializeList();
}
}
public ListSelector()
{
this.Text = windowName;
InitializeComponent();
}
When creating your new ListSelector object
ListSelector ls = new ListSelector();
ls.CardList = your mainform list of IOModule here
ls.ShowDialog();

Test assert fail: Null reference exception. Object Reference not set to an Instance of an object

Ok so I have one line of code that is causing me grief, but unfortunately without it, my program breaks. It is the only way I can think of (aside from completely restructuring my program) to do what I want it to do.
The purpose of this line is to select the next class to run (in the menu), which is outside of its own scope. Trouble is that the class (Login) exists within the scope of the menu.
Here is the line:
LoginView.Menu.SetMenuView();
Can anyone suggest a better way of writing this?
Technically, there is nothing wrong with the line, the program works without a hitch. But when I run a test, the test fails due to the Null Reference Exception.
Here is the classes it appears in:
Controller:
public void Show_Login(Menu_View Main_Menu)
{
// Creates an object of the User_LoginView.
// Set the Parent Form of the Child window
// Display the new form.
User_LoginView LoginView = new User_LoginView();
LoginView.MdiParent = Main_Menu;
// This line changes the reference to the "Menu" variable for later use.
LoginView.Menu = Main_Menu;
LoginView.Show();
}
public static void Compare_Login(User_LoginView LoginView)
{
// Creates a new object of User_Model and populates it from the User_Controller.
User_Model AccessModel = new User_Model();
AccessModel.Name = screenName;
AccessModel.Pwd = screenPwd;
// Runs the Login Comparsion in the Database_Facade, and passes in the Model.
Database_Facade Database = new Database_Facade();
Database.GetLoginAccess(AccessModel);
// screenAccess used for testing.
screenAccess = AccessModel.AccessLevel;
Menu_View.accessLevelSet = AccessModel.AccessLevel;
// If the return is placed here, the assert passes, but the rest of the code
// becomes unreachable.
// return;
// Compares the returned AccessLevel.
// if it is corect; closes the Login and runs the SetMenuView method,
// if it is incorrect; shows an error.
if (AccessModel.AccessLevel > 0)
{
Console.WriteLine("Access Level " + AccessModel.AccessLevel);
LoginView.Menu.SetMenuView();
LoginView.Close();
Menu_View.accessLevelSet = AccessModel.AccessLevel;
}
else
{
ErrorCodes_Controller LoginError = new ErrorCodes_Controller();
LoginError.WrongLoginError();
}
}
View:
public partial class User_LoginView : Form
{
// This is where the new reference is set, for when it gets called
// at the end of the Login Comparison.
public Menu_View Menu { get; set; }
public User_LoginView()
{
InitializeComponent();
}
private void btnLogin_Click(object sender, EventArgs e)
{
User_Controller.Check_Login(this);
}
}
Here is the test:
[TestMethod()]
public void Compare_LoginTest()
{
User_LoginView LoginView = new User_LoginView();
User_Controller.screenName = "ben";
User_Controller.screenPwd = "password";
User_Controller.Compare_Login(LoginView);
int actual = User_Controller.screenAccess;
int expected = 1;
Assert.AreEqual(expected, actual);
}
In your test method, you are not setting a value for LoginView.Menu, which you are doing in Show_Login().
Therefore, when you call Compare_Login() from the test, Menu is null.
It might be worthwhile changing the constructor of LoginView to accept the menu, and ensure that your test passes something in.

Categories

Resources