0

I have two forms, form1, which the user can select the file to edit, and form2 which the user can edit the data. Below code for form1 listView in which the user selects the file to edit:

private void listView1_DoubleClick(object sender, EventArgs e)
{
    _AccountData = File.ReadAllLines(listView1.SelectedItems[0].Tag.ToString());
    Form2 passForm = new Form2();
    passForm.ShowDialog();
}

Here is the code for the second form, in which the user should be able to edit data:

 private void Form2_Load(object sender, EventArgs e)
{
    Form1 f1 = new Form1();
    string[] accData = f1.AccountData;
    string[] test1 = accData.ToString().Split(';');
    oldUsername.Text = test1[0];
    oldPass.Text = test1[1];
    //and so on    
}

Property to pass data:

private string[] _AccountData;
public string[] AccountData
{
    get { return _AccountData; }
    set { _AccountData = value; }
}

This is what I use to pass data between forms, but whenever I try to display data, it always hangs on the second form, because it shows that f1.AccountData is null, even though there is data in it (if I put a breakpoint it shows data in the first form, but it is not passed to the second).

I am relatively new to working with several forms, so I do not know for sure what needs to be edited for the code to work. Why is it showing that the value is null on the second form, when it shows value in the first form?

EInherjar
  • 339
  • 6
  • 17
  • Create a constructor or a property in Form2 and pass or assign _AccountData values to it and then show the form. – G J May 29 '17 at 11:30
  • This has been asked a million times before and (big surprise) the answer is correct. Voted to close – EpicKip May 29 '17 at 11:48

1 Answers1

2

Following line creates a totally new instance of Form1:

Form1 f1 = new Form1();

New instance has new set of controls and properties which are not related to Form1 instance which you had before opening Form2.

To make your code working you should pass reference to existing instance of Form1 to Form2 instead of creating new instance of Form1.

Or better - pass only data to Form2 without passing a reference to another form. E.g. use class Account to hold account data (instead of the array of string):

public class Account 
{
    public string UserName {get;set;}
    public string Password {get;set;}
    // etc
}

Then in Form2 constructor add parameter of Account type and initialize form controls with values from account instance:

public Form2(Account account)
{
    InitializeComponent();
    oldUsername.Text = account.UserName;
    oldPass.Text = account.Password;        
}

And provide values when creating Form2:

private void listView1_DoubleClick(object sender, EventArgs e)
{
    // better store `Account` instance in private fields 
    _AccountData = File.ReadAllLines(listView1.SelectedItems[0].Tag.ToString());
    Account account = new Account {
       UserName = _AccountData[0],
       Password = _AccountData[1]
       // etc
    };

    Form2 passForm = new Form2(account);
    passForm.ShowDialog();
}
Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • How exactly do I pass reference from the existing form? And how to pass data directly? Make the fields public? I would like to avoid that though. – EInherjar May 29 '17 at 11:36
  • @EInherjar: Make a public method in `Form2` that allows external callers to set the values. Then make `Form1` call that method and set the values. I see no issue in using properties as opposed to a method; unless you are e.g. trying to adhere to company coding standards. – Flater May 29 '17 at 12:01
  • Okay, thank you for the lengthy reply, however I have a slight problem with making the class and its fields public. Is it best practice to do so? How else would I protect the fields? – EInherjar May 29 '17 at 12:11
  • @EInherjar you had public `AccountData` property - nothing changed from security point :) Though if you still worry that someone can modify `Account` values, you can make all properties read-only `public string UserName {get;}` and set them in `Account` constructor. Nobody will be able to change property value after object construction – Sergey Berezovskiy May 29 '17 at 12:17
  • I do not understand completely, how do I build the class then? I would like to make this as secure as possible, if the account or the fields are all public, doesn't that make them unsafe? Unless I'm misunderstanding something? Can you show an example please. – EInherjar May 29 '17 at 12:31
  • @EInherjar how did you protect `AccountData` property? – Sergey Berezovskiy May 29 '17 at 12:32
  • Just as above `private string[] _AccountData;` – EInherjar May 29 '17 at 12:37
  • @EInherjar no, above you have public property with `set { _AccountData = value; }` – Sergey Berezovskiy May 29 '17 at 12:38
  • I still do not understand what you mean, so if you want, can you please edit the code to make it more secure, if not, I would like to thank you for the lengthy reply. – EInherjar May 29 '17 at 12:44
  • 1
    @EInherjar if you really want to add some security to your application, then I would start with storing password hashes instead of raw passwords. Making properties readonly, private or public will not make your application secure, because reflection can be used to get any data from your classes. You should use readonly properties if you don't want the data to be modified after it was assigned, properties with private setter if you want to modify data only withing class which holds data, or public modifier if you allow to modify data by any other object – Sergey Berezovskiy May 29 '17 at 12:47