I have two Forms. Say FormA, FormB.
From FormA i called FormB using frmB.Sho开发者_开发技巧w();
In FormB, i've two textboxes and a combobox controls. Assume User enters some data in those two textboxes and selected an item from combobox in Form2 and clicked an OK button.
After the click i want those textboxes user entered values, combobox selected item value back to FormA.
How can i achieve this using C#.
I approached the simple way .. little embellishments..
create public variables in your form class i.e.
public string passVariable1 = "";
if you have text boxes go to properties, then click on the lightning bolt and double click on the empty TextChanged eventhandler. This will create a code snippet in the code begind that gets executed when the content of the textbox changed .. in this code block assign the content of the text box to your corresponding public variable.
i.e. my public variable was
public string issue = "";
private void txtIssue_TextChanged(object sender, EventArgs e) { issue = txtIssue.Text; }
Add a button and create a click event for this button (simply double click on the button in the design pane). In the click event code block set the dilog result to ok and hide the
this.DialogResult = DialogResult.OK;
this.Hide();
In the parent window code check on the dialog result and grab the form data from the child form's public variables
if (f.ShowDialog() == DialogResult.OK) { string b = f.issue; string e = f.year; string f = f.month; };
In the scenario that you are describing I would probably call frmB.ShowDialog()
rather than frmB.Show()
.
// Inside FormA open frmB as a modal dialog waiting for
// OK or Cancel result using the following statement
if (frmB.ShowDialog() == DialogResult.OK)
{
// Retrieve selected values from frmB here (while frmB is still not disposed)
}
The benefits of ShowDialog()
are that you:
- Get the return value from the form easily allowing you to determine that OK (rather than cancel) was clicked to close it.
- The form is not immediately disposed when closed thus allowing you to retrieve the values that you want.
- By opening frmB as a modal dialog you avoid having to check for the complexities that may occur if your user starts interacting with formA while frmB is open.
NOTE: When designing frmB you have to set the DialogResult
property of the OK button-control to DialogResult.OK
in order for the form to return the correct DialogResult when this button is pressed (alternatively can also set this.DialogResult
in the OK button's Click event handler)
Or you could pass an object from FormA to FormB and bind its properties to the controls in FormB. If you want FormA to be notified when you click OK button you could declare an event in your data container class, subscribe to it in FormA and fire it from FormB.
Be DataContainer some class you define
public class DataContainer
{
public event EventHandler AcceptedChanges;
protected virtual void OnAcceptedChanges()
{
if ((this.AcceptedChanges != null))
{
this.AcceptedChanges(this, EventArgs.Empty);
}
}
public void AcceptChanges()
{
this.OnAcceptedChanges();
}
public string Text1 { get; set; }
public string Text2 { get; set; }
}
in FormA:
private void button4_Click(object sender, EventArgs e)
{
DataContainer data = new DataContainer();
data.Text1 = "text1";
data.Text1 = "text2";
Form2 frm = new Form2();
frm.Data = new DataContainer();
data.AcceptedChanges += new EventHandler(data_AcceptedChanges);
frm.Show();
}
void data_AcceptedChanges(object sender, EventArgs e)
{
// your code here
}
and in FormB:
public DataContainer Data { get; set; }
private void Form2_Load(object sender, EventArgs e)
{
textBox1.DataBindings.Add(new Binding("Text", Data, "Text1"));
textBox2.DataBindings.Add(new Binding("Text", Data, "Text2"));
}
private void button1_Click(object sender, EventArgs e)
{
Data.AcceptChanges();
}
You should also implement INotifyPropertyChanging and INotifyPropertyChanged on DataContainer class to play nice with bindings.
You can create an EventHandler on FormB which FormA will subscribe to. Also, add a couple of public properties to FormB that represent that data that you want FormA to be able to use. Then, when FormB fires off the event, FormA will know to refresh his data.
Note: The key principle in this example is implementing an EventHandler (you can create your own event handler type) which notifies FormA when data is ready to be refreshed/viewed/etc. Hopefully, this example will allow you to see how you might implement an event handler for your particular situation.
Example:
FormA -
public partial class FormA : Form
{
//FormA has a private instance of FormB
private FormB formB = null;
public FormA()
{
InitializeComponent();
}
void formB_OnDataAvailable(object sender, EventArgs e)
{
//Event handler for when FormB fires off the event
this.label1.Text = string.Format("Text1: {0}\r\nText2: {1}",
formB.Text1, formB.Text2);
}
private void InitializeFormB()
{
this.formB = new FormB();
//FormA subscribes to FormB's event
formB.OnDataAvailable += new EventHandler(formB_OnDataAvailable);
}
private void button1_Click(object sender, EventArgs e)
{
this.InitializeFormB();
formB.Show();
}
}
FormB -
public partial class FormB : Form
{
//Event that fires when data is available
public event EventHandler OnDataAvailable;
//Properties that expose FormB's data
public string Text1 { get; private set; }
public string Text2 { get; private set; }
public FormB()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//Set the exposed properties, then fire off the event.
this.Text1 = this.textBox1.Text;
this.Text2 = this.textBox2.Text;
if (OnDataAvailable != null)
OnDataAvailable(this, EventArgs.Empty);
}
}
A dirty, but also fastest solution is to make those controls public. This you can do by adding the word public in the Form2.Decisgner.cs file. If FormA has a member variable or local variable of FormB, you can access the control (say TextBox1) with:
frmB.TextBox1.Text
which is now accessible outside FormB too.
How about using events and delegates? See this http://colinmackay.scot/2005/04/22/passing-values-between-forms-in-net/
I was having this same issue and came up with an idea which is a bit different. In my scenario, I am making a flashcard program for my youngest two children and I wanted to be able to carry back the answer provided to the parent form (new child form for each new flashcard question so that the parent form can update how many are left, how many correct, how many incorrect, etc.) without having to add values to a database. Seems to be overkill for something that should be simple. What I did was to create a class with 3 of each variable type. I figured three of each type would be sufficient for most jobs.
This is an example of my new class:
namespace ClassNamespace
{
public class ValueHolder
{
public int intValue1 { get; set; }
public int intValue2 { get; set; }
public int intValue3 { get; set; }
public long longValue1 { get; set; }
.
.
.
}
}
I create a new ValueHolder (ValueHolder vh;) from parent form and pass it to the child form. In the child form I create a new ValueHolder and then set it equal to the ValueHolder object sent in the child form's class constructor. Now, when the enter key is pressed (answer given), I can set vh.intValue1 equal to this.answerBox.text;... well, I have to use int.tryparse(); but you get the idea. I then only need to reference vh.intValue1 from the parent form to get the value entered.
Parent form:
for (int i = 0; i < limit; i++)
{
ValueHolder vh = new ValueHolder();
ChildClass cc = new ChildClass(vh);
MessageBox.Show(vh.intValue1.ToString()); //to test that it works
}
and child form:
ValueHolder vh;
public ChildClass (ValueHolder vhIncoming)
{
vh = vhIncoming;
}
private void answerBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
vh.intValue1 = 1234;
}
}
This seems to be the simplest solution for my scenario. I know that this question is old, but wanted to add this option for anyone in a similar position. Just add the class to your project, add more of a type or more types to the class as needed, rinse repeat for future projects.
If its on the same page you should be able to read it directly from your controls as Textbox1.Text, Textbox2.Text, Combobox.SelectedValue (i guess) But if its on different pages use Session variables like: Session["date1"] = TextBox1.Text; Session["date2"] = TextBox2.Text; Session["comboValue"] = Combobox.SelectedValue; and use them to populate your form
This would depend on how you normally design your applications.
- You could work by using a event driven system where you would create events and delegates. Mentioned by @Dave81
- Or you could create properties that return the given/selected values so that the parent can retrieve them from the object (Wanted to say Dialog but not sure about what your using).
- Or you can follow @zmilojko and just set them public, which is basically the same as creating properties but more to the dark side of coding practices :D
All these would work but it all depends on how you like your applications to be structured.
精彩评论