I am doing a registration system. In this system I use a modal, another form that is displayed when the user clicks a button.
To show the form, I use:
private void btnShowModal_Click(object sender, EventArgs e)
{
AddUserForm form = new AddUserForm();
form.Show();
}
This works great to show the form. Now this is my problem: if I create one label in this form and try to use it for reference in the primary form I get the error that it does not exist in context. Example, I've created label1 in the AddUserForm. Now I will try to use the same label in Form1 to change the text:
label1.Text = "I was created in AddUserForm and now I'm at Form1!";
...but this don't work, I get the error:
The name 'label1' does not exist in the current context.
How I can use elements in both forms? I need to add a reference? How? Thanks all in advance!
Create a Base form that creates the label. Each form can then inherit from the base form and share it that way.
public class BaseForm : Form
{
//define label
}
public AddUserForm : BaseForm
{
}
In your AddUserForm, create this property:
public string LabelText
{
get { return label1.Text; }
set { label1.Text = value; }
}
Then in your Form1, simply add this line after you create the AddUserForm instance:
form.LabelText = "I was created in AddUserForm and now I'm at Form1!";
More generally, while you could have exposed the field (it's private by default), doing so is a bad idea. Wrapping form elements in properties gives you control over exactly what the outside world can and cannot change. For example, you may not want other classes being able to change the size, location, font, etc. of the label. Or maybe you do, but if so then you add properties specifically for those things you want to be able to be changed.
I think you can try like this,
Form1.cs
private void btnShowModal_Click(object sender, EventArgs e)
{
Form2 frm = new Form2(ref this.label1);
frm.ShowDialog();
}
Form2.cs
Label labelOne = null;
public Form2()
{
InitializeComponent();
}
public Form2(ref Label lbl)
{
InitializeComponent();
labelOne = lbl;
}
private void Form2_Load(object sender, EventArgs e)
{
labelOne.Text = "A";
}
Hope it solves!
Related
I am trying to have a button in Form3 change a label's text in Form1 and Form2.
I have gotten it to work somewhat but in order to have the label change I have to have the mouse click on it. This is my current code in form 1 and 2:
label1.Text = Form3.myNameClass.myName;
and this is code in form 3
public class tournamentNameClass
{
public static string tournamentName;
}
public void button1_Click(object sender, EventArgs e)
{
myNameClass.myName = textBox3.Text;
}
How can I make it so that I dont need to press the label to get it to change?
Since you are at the start of learning, I'm not going to go in events and delegates.
My example demonstrates how you manipulate a control on Form1 from Form2 directly. You should be able to figure this out for Form3 easily by yourself, and is together a good practice of understanding.
(I want to state that there are many different methods/techniques for passing data or manipulate controls between forms, I guess this is the easiest one for you to understand as a beginner, as this is the most simplistic approach of all)
Form1 Designer
First we make label1 its modifier to Public (so we can reach it in another class) in the designer like so:
Form1 code behind
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// With the keyword "this" we pass in Form1, the current instance we are in
Form2 form2 = new Form2(this);
form2.Show();
}
}
Form2 code behind
public partial class Form2 : Form
{
private Form1 _form1;
public Form2(Form1 form1)
{
_form1 = form1;
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
_form1.label1.Text = "lets change the text";
}
}
We are passing Form1 completely in the constructor, this could easily be the label1 control alone.
Result
I think you only need to trigger a redraw on forms 1 and 2.
after you set the text of the label, try calling labelControl.Refresh()
Or you could call refresh on form1 and form2 if that's any easier (that is a bit heavy handed though)
This will instruct the forms to redraw their visual representation based on how the data is set in the form currently.
Update:
You will need to invert your logic somewhat..
Rather than having a reverence to form 3 from form 1 and form 2, you will need to have a reference to form 1 and 2 from form3.. (woah so many form)
So then your button click method would look like this
public void button1_Click(object sender, EventArgs e)
{
form1.label1.Text = textBox3.Text;
form2.label1.Text = textBox3.Text;
form1.label1.Refresh();
form2.label1.Refresh();
}
I have a main form which allows opening another forms (at this moment up to 3 form).
I am using following code to open a form from main form:
public partial class network : Form
{
p1 _p1 = new p1();
p2 _p2 = new p2();
public network()
{
InitializeComponent();
}
private void Phone1_Click(object sender, EventArgs e)
{
_p1.Show();
//Phone1off.Visible = true;
//networklog.Items.Add("Phone 1 added");
}
above code working fine at the moment.
Now, the problem is when let's say I have opened two forms from main form and have type something in the child form1 then want to display it in child form2. I am unable to do it.
at this moment I have coded as below to achieve this:
public string TextBoxValue
{
get { return textBox1.Text; }
set { textBox1.Text = value; }
}
private void button2_Click(object sender, EventArgs e)
{
p2 _p2 = new p2();
textBox1.Text = "";
textBox1.Text = "Calling Phone 2";
_p2.TextBoxValue = "Phone 1 Calling";
}
also for your information all my child forms will have same layout. so I am inheriting all from 1 design (say form1: form2)
I will appreciate your response
You are looking for DataBinding to have a Model (a simple class, List or Datatable) being watched by multiple controls.
Model
First have a class that will act as the model:
public class PhoneModel
{
public string SomePhone { get; set; }
}
Compile this so the designer can find that class when you add ...
BindingSource
... to the designer of your Network Form:
Set the DataSource property to an object and choose the PhoneModel class.
Set the Modifiers property to Protected
Do the same for your base class called P.
On the TextBox select in the properties the DataBinsdings settings:
Subclassed form handling
I'm not sure why have two different classes but let's keep that as a fact.
Add an constructor to each of your classes that will accept the BindingSource instance from the caller. We use that instance to update the per form BindingSource.
public class P1 : P
{
public P1(BindingSource bs):base()
{
base.bindingSource1.DataSource = bs.DataSource;
}
}
Do this for every form you have that needs to synchronize its values
Wire your Network form to the P1 and P2 instances
In the click events of your buttons on the Network form start P1 or P2 by providing the BindingSource in the constructor:
private void button1_Click(object sender, EventArgs e)
{
new P1(this.bindingSource1).Show();
}
And have your model instantiated, I used the Form_Load event to do that.
private void Network_Load(object sender, EventArgs e)
{
this.bindingSource1.DataSource = new PhoneModel { SomePhone = "foo" };
}
That is all there is. When you enter values in one of the TextBoxes all values on all open forms will get updated due to the BindindingSource that updates all controls that it is bounded to as can be seen in this demo:
I would recommend using .showDialog() instead of .show(). This way, the data in _p2 doesn't disappear when _p2 closes. You'll still be able to access the data from _p2 in _p1. Before you call .showDialog(), you can set the values of the variables of _p2 using the data from _p1. Then, when you do finally call .showDialog(), it will display all the data you set earlier.
I have Form1 that has a toolStripStatusLabel. Then Form2 that has button and is there string with value ( Hello ). I need if i click on the button, show value "Hello" to toolStripStatusLabel in Form1. toolStripStatusLabel is set to public.
This show me :
Cannot implicitly convert type 'string' to 'System.Windows.Forms.ToolStripLabel'
public partial class form2 : Form
{
public form2()
{
InitializeComponent();
}
Form1 form = new Form1();
string example = "hello";
private void button1_Click(object sender, EventArgs e)
{
form.toolStripLabel1 = example;
}
}
}
Well you'd need to say formtoolStripLabel1.Text = example; rather than what you said. However, this will not affect the one from the original instance of Form1. If you wanted to affect the original instance of Form1, you'd make the tooStripLabel public static rather than just public so that all classes can affect it immediately.
You have to set the Text property in the ToolStripLabel object.
form.toolStripLabel1.Text = example;
Take a look at this.
You should you:
form.toolStripLabel1.Text = example;
instead of:
form.toolStripLabel1 = example;
And you might want to take a look at this: http://www.codeproject.com/Articles/14122/Passing-Data-Between-Forms
If you want to share data between 2 forms
Lets say I have two forms ( Form1 And Form2 ).
Form1 has a PictureBox
Form2 I has an OpenFileDialog
Form1 is the main form, so when I run the project I see Form1.
How can I change the Image in the PictureBox in Form1 from Form2?
How do I pass a value from a child back to the parent form?
Basically, expose the value that gets returned in the open file dialog with some property and let the parent form grab it.
In the Program.cs file you can set any value, either FormOptions to the form's instance .
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var frm = new Form1();
// Add the code to set the picturebox image url
Application.Run(frm);
}
In addition you can add the Constructor to Form1 and pass the parameter via constructor.
Pass one form as a parameter to a constructor of the second form or add a method that passed the reference. After you have the reference to your form you can do whatever you want with the from.
Whether to share picture box as a public member is up to you. However, I would suggest making a public method SetImage() in the first form. Second form would call form1.SetImage().
[Update]
Wait, why do you need to set image from OpenFileDialog, you just need receive fileName from the dialog, and then open the file and load into the form.
Like this:
private void button1_Click(object sender, EventArgs e)
{
using (var dialog = new OpenFileDialog())
{
var result = dialog.ShowDialog();
if (result != DialogResult.OK)
return;
pictureBox1.Image = Image.FromFile(dialog.FileName);
}
}
This is code inside of Form1.
[Update]
Here is the basic idea how to access one form from another.
public class MyForm1 : Form
{
public MyForm1()
{
InitializeComponent();
}
public void SetImage(Image image)
{
pictureBox1.Image = image;
}
private void button1_Click(object sender, EventArgs e)
{
var form2 = new Form2(this);
form2.Show();
}
}
public class MyForm2 : Form
{
private MyForm1 form1;
public MyForm2()
{
InitializeComponent();
}
public MyForm2(MyForm1 form1)
{
this.form1 = form1;
}
private void button1_Click(object sender, EventArgs e)
{
form1.SetImage(yourImage);
}
}
You can very simply do this.
At first change your code(in Form1) that show Form2 to looks like this:
<variable-of-type-Form2>.ShowDialog(this);
or if you dont want form2 to be modal
<variable-of-type-Form2>.Show(this);
Next when you got path to image, you can access pictureBox like this
((PictureBox)this.Owner.Controls["pictureBox1"]).Image=Image.FromFile(<filename>);
Assume that you have PictureBox on Form1 with name "pictureBox1"
Ideally, you want to structure your code in a ModelViewController pattern. Then, you simply have a reference in your model to the image in the picture box. When interacting with the OpenFileDialog in Form2, you would call your model adapter interfaces hooked into the views (Form1 and Form2) to change the image being held in the model. In short, you need a callback from the view to the model. If you don't want to redesign your code to be MVC, simply have a shared object holding the image reference that both Form1 and Form2 receive in their constructors, so they can both modify it.
This might be a novice question. :). Consider the following scenario.
Suppose we have two windows forms that are already "loaded" (i.e You
can see both the forms)
Form 1 contains a textbox and a "submit" button while the form 2
contains a text lable.
The user can enter a string in the textbox and press submit on
form 1 The lable on form 2 should
be updated with the new text.
What is the best way to achive this? Any formal way to do this? I don't want to increase the variable scopes unnecessarily.
Edit : Both the forms belong to same application
Assuming these forms are part of the same application, you need to have a common data model where you keep your data and then your forms "bind" to this data model. Check out M-V-C or M-V-VM patterns. This would also nicely separate your UI from your data.
Do some research on model view controller pattern and databinding in winforms.
Create a seperate controller class and reference this in the two forms, which implements INotifyPropertyChanged. On the controller, have a property which propagates the changed events from and to the forms.
Form1 triggers Form2 to open. Form2 has overloaded constructor which takes calling form as argument and provides its reference to Form2 members. This solves the communication problem. For example I've exposed Label Property as public in Form1 which is modified in Form2.
With this approach you can do communication in different ways.
Download Link for Sample Project
//Your Form1
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm = new Form2(this);
frm.Show();
}
public string LabelText
{
get { return Lbl.Text; }
set { Lbl.Text = value; }
}
}
//Your Form2
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private Form1 mainForm = null;
public Form2(Form callingForm)
{
mainForm = callingForm as Form1;
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
this.mainForm.LabelText = txtMessage.Text;
}
}
alt text http://ruchitsurati.net/files/frm1.png
alt text http://ruchitsurati.net/files/frm2.png