Passing Data Between Forms

Passing data between forms


Form1 frm = new Form1();

frm is now a new instance of class Form1.

frm does not refer to the original instance of Form1 that was displayed to the user.

One solution is, when creating the instance of Form2, pass it a reference to your current instance of Form1.

Passing data between C# forms

The code that you put in the sample project (that you provided as a link in the comments) should be in your question. Given that it becomes much easier to understand what you're trying to do and to give you a workable solution.

I would suggest creating a "DataTransferObject" and pass that between each form.

public class Dto
{
public string Text;
}

The code in MainWindow would then look like this:

    private void button1_Click(object sender, RoutedEventArgs e)
{
var dto = new Dto();
window2 win2 = new window2();
win2.Dto = dto;
win2.ShowDialog();
textBox1.Text = dto.Text;
}

And the code in window2 would look like this:

    public Dto Dto;

private void textBox2_TextChanged(object sender, TextChangedEventArgs e)
{
if (this.Dto != null)
{
this.Dto.Text = textBox2.Text;
}
}

That is one way - out of about a million - of transferring data between forms. An advantage of using a data transfer object is that it begins you on the road of separating your data from your UI, and that is generally a very good thing to do.

Passing data between forms is null

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();
}

Safest way to pass data between forms in c# winforms

So the reasoning that you have given for just having a lot of public static data is not correct. It is no more or less secure from malicious attempts of another processes to access the information. It's in memory no matter what you do, so a malicious process (with sufficient privileges) can get at it no matter what, but they're likely to have a bit of a hard time of it no matter what as well. If you have a malicious process/user with that level of permissions you've already lost the fight; they can already do whatever they want.

The problems with storing all of your data in public static fields is merely a matter of effective development, not of actual security. When the data can be modified from anywhere in your entire program at any time it makes it extraordinary hard to understand what's going on in the program at any one point in time, it makes bugs really hard to track down as there could be problems almost anywhere in the code, it makes bringing in new developers to a project really hard because they can't just open up a class or two and understand them, they need to understand the entire application to be able to reason correctly about what's going on in any one part, due to the high level of coupling in your application.

You should strive to reduce coupling of various modules in your application by keeping the data more localized. This allows a developer to look at a single module (whether that be a form, a user control, some worker class, etc.) and only need to understand that class in front of them without needing to understand every single point in the entire application that also touches the same variables.

You also need to be very concerned about threading issues when you're accessing public static variables from multiple threads, since you almost certainly are going to require multiple threads in a winform application.

Finally, if you're storing all of your data statically it means that you'll never be able to have multiple instances of your forms. Most forms that you'll write, from a logical perspective, shouldn't require that there never be more than one of them in an application. If their data is localized to just them there isn't any problem creating a second form. If all of the data is static, then the forms will end up fighting with each other over that data.

As for how to accomplish this, the primary goal here should be to keep data scoped as narrowly as you are able to (which is something that you should generally strive for throughout all types of programming) without allowing variables to be accessible in places where they don't need to be accessed.

The case you've described is a fairly straightforward problem to solve. If a form is creating another form that needs some data upon construction, if that data is essential to the use of that other form then just create parameters in the constructor for that data. The form (or whatever else) creating it can then pass in that required data. If the data isn't required, or it isn't required right at construction, then the other option is to have properties that allow the "owner" of that form to pass in the data that is needed. Doing this isn't really any more complex than creating a public static field; it's simply creating a public non-static property.

Now that this data isn't static you know that, rather than being accessed from anywhere, that information is going to be provided from whoever is "owning" that particular instance of the form. You're limiting the scope of where the data can be accessed to place that needs it, and the place that has it, rather than "everywhere".

How can I pass data between forms?

As several noted, if you use a tab control, you can put that form as a sub-form, and then in most cases no code at all will be required.

However, there are quite a few ways to pass values.

The cleanest code, and no global variables?

I suggest this approach:

You don’t pass the values, but “grab” the previous form object.

So, in your 2nd forms code module, you declare a variable called frmPrevious. This var is declared at the forms module level.

So, you code module will look like this:

Option Compare Database
Option Explicit

Public frmPrevious As Form

Now, in the forms on-open event, you do this:

Private Sub Report_Open(Cancel As Integer)

Set frmPrevious = Screen.ActiveForm

End Sub

Note that your current form does NOT become the active form until the open event is completed. In fact, you can even put the above code in the forms on-load event.

Ok, now.

Your new payment button code?

With the above, you are free to grab “any” values you want from the previous form.

Eg:

Me.CompanyName = frmPrevious!CompanyName
Me.member_id = fromPrevous!ID

Etc.

So, the above is nice, since then you can pass/use and reference ANY value or control from the previous form.

However, you should not be re-copy the LastName box, but in fact ONLY set the customer_ID or some such to the customer, and then you can in the future reference/gget phone number, city etc.

Re-copy of a value is very very BAD approach, as you are breaking the relational design, and you wind up writing tons and tons of more code then is required.

IN fact, in your code, likely the new payment button has to go to a NEW record FIRST, else the above code will start to overwrite existing values.

And, if the user hits new payment, and THEN decides to bail out and not add? Well, then you going to wind up with blank records.

What this really means is you should put the code that “copies” and “sets” the values from the previous form in the before insert event. This event ONLY will fire for new records, so you don’t need special code to check or worry if you going to accident over-write values in a known good record.

WinForms passing data between Forms

You should try to split your UI-code and your database code. This is called Layering (MVVM, MVC, MVP,...) but you don't have to!

There are several ways:

1) Make a class that both forms can reference and execute your database logic there. (that would be the cleanest way for now)

2) Create an Event in your Form with the menu and react on it in the other Form

3) Your menu Form holds a reference to the other Form and executes a Method on it passing the selected subitem.

In code

1

public static class SqlClass
{
public static void ExecuteQuery(string menuItem)
{
//execute query
}
}


Form 1
//menu changed...
SqlClass.ExecuteQuery(menuItem)

2

Form1:
public event EventHandler<string> MenuItemChanged;

//menu changed...
if(this.MenuItemChanged != null)
this.MenuItemChanged(this, menuitem)


Form2:
public Form2(Form1 otherForm)
{
InitializeComponent();
_otherForm.MenuItemChange += //... handle your sql code
}

3

private readonly Form2 _otherForm;

public Form1(Form2 otherForm)
{
InitializeComponent();
_otherForm = otherForm;
}

//menu changed...
otherForm.ExecuteQuery(menuitem);

For the examples, Form 2 is the form where you want to execute your query because there is the Method/Event-Handler defined that will interact with your database.

To understand the solution, you need a more high level perspective - you get an information in code behind of a Form (a Class) and you want to consume that information somewhere else.

In general you need a reference to the Form that holds the information you are interested in and it tells you the information when changed (Event) OR

the information source tells every interested destination (calls a Method). Then the Information source hold the references to the consumers.

Both concepts are the same just the direction of the communication (and reference) changes.

The alternative (Option 1) is that you move your information destination somewhere else (e.g. in a static class) and consume it there. The Mechanism of passing the information is pretty much the same (via a parameterized Method call) but it encapsulates the UI-colde (Form) from the Database code (SQL query execution)



Related Topics



Leave a reply



Submit