Passing Variable Between Winforms

Passing variable between winforms

Pass any information you want to in to the constructor of Settings form, and provide accessor methods for things you need out of there.

public class SettingsForm : WinForm
{
private string m_Data;
private int m_nExample = 0;

// ctor
public SettingsForm(string _data)
{
m_Data = data; // you can now use this in SettingsForm
} // eo ctor

public int Example {get{return(m_nExample);} }
} // eo class SettingsForm

In the above "example" you can construct a SettingForm with a string and get at an integer it may use. In your code:

private void toolStripBtnSettings_Click(object sender, EventArgs e)
{
PageInfoEventArgs args = new PageInfoEventArgs(SomeString);
this.OnPageInfoRetrieved(args);

SettingsForm settingsForm = new SettingsForm("some data to pass");
settingsForm.ShowDialog();

int result = settingsForm.Example; // retrieve integer that SettingsForm used
}

How do I pass variables between methods in C#?

Your example has a Form named Form1 that has a Button named button1, a TextBox named textbox1 and a Label named label1.

The scenario you are attempting is:

  1. user enters some text into textbox1
  2. user clicks on button1, this will save the current value from textbox1
  3. user clicks on label1, this will display the value that was stored in the previous step

It is important to understand that in this scenario we are not trying to pass a value between 2 methods because the button click and the label click can occur independently of each other, so really this is like the memory store (M+) and memory recall (MR) buttons on calculator.
To achieve this storage you should create an instance variable (sometimes referred to as a member variable) on the Form1 class, this will be accessible to the other methods on the same instance of the Form1 class.

See Working with Instance and Local variables for a practical explanation

  1. Create a field or a property to store the value, for your specific example either would work, however to become familiar with C# techniques I would recommend you start with a property, as that better encapsulates your scenario of storing the value for later use and later to potentially augment how and where the value is actually stored.

    See What is the difference between a field and a property?
    for a healthy discussion

    Until you need to change the implementation, you can simply use an Auto-Property

     public string StoredText { get; set; }
  2. Now in the click event handler of button1 we can set the value of the StoredText property on the Form1 instance

     private void button1_Click(object sender, EventArgs e)
    {
    this.StoredText = textBox1.Text;
    }

    set is a term we use for saving a value into a property in c#
    Note the use of the this keyword, it is optional in this case, or can be inferred by the compliler, it indicates that we want to reference a member on the instance of the class, not a variable that might have the same name within the same method scope of the line of code that is executing.

  3. Finally in the click event handler of label1 we can get the value that was previously stored in the StoredText property in the Form1 instance.

     private void label1_Click(object sender, EventArgs e)
    {
    // Get the "StoredText" variable and use it
    label1.Text = this.StoredText;
    }

    get is a term we use for accessing a value from a property in c#
    this is not required, but can be helpful to understand that we are accessing a member that is outside of the current method scope.

Together this looks something like:

namespace Example
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

/// <summary>Saved value from see <see href="textBox1"/></summary>
public string StoredText { get; set; }

private void button1_Click(object sender, EventArgs e)
{
this.StoredText = textBox1.Text;
}

private void label1_Click(object sender, EventArgs e)
{
// Get the "StoredText" variable and use it
label1.Text = this.StoredText;
}
}
}

What you may not have noticed is that textBox1 and label1 are themselves infact instance variables that are initialized in a separate code file when InitializeComponent() is executed in the constructor.
For this reason you do not need to store the value at all and you could simply re-write the client event handler for button1 to write directly to label:

label1.Text = textBox1.Text;

It is possible to pass variables directly between methods without an intermediary store, this is a lesson for another day and will involve return statements and/or parameters on your methods.
In this scenario however, neither return or additional parameters on these methods cannot be used because these are event handlers that need a specific method signature to operate as expected.

Passing Values Between Windows Forms c#

You need to put loginData into a local variable inside the frmVoiceOver class to be able to access it from other methods. Currently it is scoped to the constructor:

class frmVoiceOver : Form
{
private NewDataSet _loginData;

public frmVoiceOver(NewDataSet loginData)
{
_loginData = loginData;

InitializeComponent();
}

private void btnVoiceOverNo_Click(object sender, EventArgs e)
{
// Use _loginData here.
this.Close();
Form myFrm = new frmClipInformation();
myFrm.Show();
}
}

Also, if the two forms are in the same process you likely don't need to serialize the data and can simply pass it as a standard reference to the form's constructor.

Google something like "C# variable scope" to understand more in this area as you will encounter the concept all the time. I appreciate you are self-taught so I'm just trying to bolster that :-)

Pass data between 2 already OPEN winforms (C#)

You can use events to pass messages to disconnected entities. You can listen for events in Form1 and raise them from Form2. This is from memory, don't fully expect it to compile.

Create a class that is the "event hub".

public static class EventHub
{
public static event EventHandler<EventArgs> formMessageHandler;

public static void OnFormMessage(object sender, EventArgs e)
{
formMessageHandler?.Invoke(sender, e);
}
}

In Form2 button click event raise the event. You can use the sender reference directly to access public members or you can put relevant data into an EventArgs.

EventHub.OnFormMessage(this, EventArgs.Empty);

In Form1, maybe in the constructor, wire up a listener:

EventHub.formMessageHandler += some_method_you_write;

Now, when you click the button in Form2, Form1 will receive a reference to Form2 in some_method_you_write(). Or, you can actually use the EventArgs to pass data so you don't need to make any public controls on Form2.

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.

Pass variable between forms when clicking button

I would do it a different way. I'd separate the code between the UI handling and the business logic layers. So your scenario would run in such a way:

  1. The first form issues an event notifying that the button with certain semantics has been activated. The data needed for the processing is included into the event's data.
  2. The business logic listens to this event, and decides to issue a command on the second form. It calls an appropriate method on the form's class, passing the needed information as a parameter (and maybe preprocessing the parameter if needed).
  3. The second form receives the command from the business logic and updates the view.

This way the problem doesn't arise at all.


Example: (I'm not the winforms expert, beware it can be totally wrong from the POV of best winforms practices.)

Part 1 (first form):

class ProcessingActivatedEventArgs : EventArgs
{
public ProcessingActivatedEventArgs(int data) { MoreData = data; }
public int MoreData { get; protected set; }
}

class Form1 : Form
{
private int currentData;
public event EventHandler<ProcessingActivatedEventArgs> ProcessingActivated;
void OnButtonClick(object sender, EventArgs args)
{
// ...
if (ProcessingActivated != null)
ProcessingActivated(new ProcessingActivatedEventArgs(currentData));
}
}

Part 2: (business logic)

class Controller
{
Form1 f1;
Form2 f2;

void StartFirstForm()
{
f1 = new Form1();
f1.ProcessingActivated += OnProcessingActivated;
f1.Show();
}

void OnProcessingActivated(object sender, ProcessingActivatedEventArgs args)
{
int data = args.MoreData;
f1.DisableProcessingRequests();
model.ProcessingFinished += OnProcessingFinished;
model.StartProcessing(data);
if (data > 0)
f2.DisplayDataProcessing(0, data);
else if (data < 0)
f2.DisplayDataProcessing(data, 0);
else
throw new SomeCoolException("impossible data");
}
}

Part 3: (second form)

class Form2 : Form
{
public void DisplayDataProcessing(int lower, int upper)
{
// ... update the UI
}
}

Note that this implementation ties the Controller and forms tighter than it could be done. In WPF, the decoupling is achieved by using the appropriate DataContext (but I don't know how to do it properly in WinForms).



Related Topics



Leave a reply



Submit