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.
Related
Method of the 1st Form Class:
private void englishToolStripMenuItem_Click(object sender, EventArgs e)
{
this.Hide();
var Editor = new Editor();
Editor.Engprop = 1;
Editor.Closed += (s, args) => this.Close();
Editor.Show();
}
Method of the 2nd Form Class:
public partial class Editor : Form
{
public int Engprop { get; set; }
public Uri MyProperty { get; set; }
public Editor()
{
InitializeComponent();
webBrowser1.ScriptErrorsSuppressed = true;
}
Uri temp = new Uri("file:///C:/Users/PC/Desktop/projese302/newtmp.html");
Uri eng = new Uri("file:///C:/Users/PC/Desktop/projese302/engtemp.html");
private void Editor_Load(object sender, EventArgs e)
{
if (Engprop==1)
{
webBrowser1.Navigate(eng);
}
}
I am trying to do that when Engprop becomes 1 (when a user clicks the item of the ToolStripMenu), it should navigate the eng URL but it doesn't work properly. I will be grateful for your help.
I suppose the Editor_Load method is called from the OnLoad event of the form.
If so, I'm not sure when this event is raised... Can be after the constructor (it explain why you have this problem) or after the Show method (in this case, I don't know why it doesn't work)
Try to check if the event is raised before or after you set the Engprop property (debug + breakpoints)
In any way, I think your code has a lack of architecture, since who use your Editor class need to know that can change the Engprop only between the constructor and the Show method.
I think you can make a better/reusable code if:
Set the Engprop property as read only and accept his value in the constructor: this is usually done when the language is set when someone instantiate your class and will never change
In the setter of the Engprop raise an event when it changes: this is done when you allow to change the language also after the instance is created. So, your Editor class can add an handler to this event and change the language of the page every time someone changes this property
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!
How to send textbox value to textbox between two forms without Show()/ShowDialog() by button?
I want to textBox will get value without open form.
To access the textbox data you need to use: textBox1.Text
a form is an object so you can define a method that updates the text box value (you can expose the textbox itself with a public accessor)
To pass information from a parent from to a child form you should create a property on the child form for the data it needs to receive and then have the parent form set that property (for example, on button click).
To have a child form send data to a parent form the child form should create a property (it only needs to be a getter) with the data it wants to send to the parent form. It should then create an event (or use an existing Form event) which the parent can subscribe to.
An example:
namespace PassingDataExample
{
public partial class ParentForm : Form
{
public ParentForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ChildForm child = new ChildForm();
child.DataFromParent = "hello world";
child.FormSubmitted += (sender2, arg) =>
{
child.Close();
string dataFromChild = child.DataFromChild;
};
child.Show();
}
}
}
namespace PassingDataExample
{
public partial class ChildForm : Form
{
public ChildForm()
{
InitializeComponent();
}
public string DataFromParent { get; set; }
public string DataFromChild { get; private set; }
public event EventHandler FormSubmitted;
private void button1_Click(object sender, EventArgs e)
{
DataFromChild = "Hi there!";
if (FormSubmitted != null)
FormSubmitted(this, null);
}
}
}
I don't know what exactly you mean by saying "without Show()/ShowDialog()", but that is not relevant anyway or I'll just assume here further that you have both windows open (doesn't matter how you accomplished that).
You would like to avoid much coupling between two forms, especially not implementation details like a textbox etc. You could work with delegates and events to trigger the "sending" of data between your two forms. You can then easily pass event data and your subscribed other form (or any other object as a matter of fact) doesn't know the exact implementation details of your form, it only knows the data it will receive through the delegate (event). I am not going to post all code here, because it is already nicely explained at following URL: http://www.codeproject.com/Articles/17371/Passing-Data-between-Windows-Forms .
I would like to load the items that were declared in class file when the Form loads can any one give me an idea
My class file code is as follows
namespace ACHDAL
{
public class TansactionCode
{
string[] strTransactionCodes ={"20","21","22","23","24","25","26","27","28","29","30","31","32","33","34",
"35","36","37","38","39","41","42","43","44","46","47","48","49","51","52","53","54","55","56","80",
"81","82","83","84","85","86"};
}
}
Would like to load all these in to the combo box when the Form loads if any thing has to be done in this code please let me know.
You populate combo boxes by setting their DataSource property (see here for more details on what you can bind to them).
To do this you'll need to expose the list first, so put it into a property. This is how the form will access it, after creating a new instance of the class.
public string[] TransactionCodes
{
get { return strTransactionCodes; }
set { strTransactionCodes = value; }
}
Then do this on the FormLoad event
eg
private void Form1_Load(object sender, EventArgs e)
{
TansactionCode trans = new TansactionCode(); // Create new instance
combobox.DataSource = trans.TransactionCodes; // Access the list property
}
Although there are some similar questions I’m having difficulties finding an answer on how to receive data in my form from a class.
I have been trying to read about instantiation and its actually one of the few things that does make sense to me :) but if I were to instantiate my form, would I not have two form objects?
To simplify things, lets say I have a some data in Class1 and I would like to pass a string into a label on Form1. Is it legal to instantiate another form1? When trying to do so it looks like I can then access label1.Text but the label isn’t updating. The only thing I can think of is that the form needs to be redrawn or there is some threading issue that I’m unaware of.
Any insight you could provide would be greatly appreciated.
EDIT: Added some code to help
class Class1
{
public int number { get; set; }
public void Counter()
{
for (int i = 0; i < 10; i++)
{
number = i;
System.Threading.Thread.Sleep(5000);
}
}
}
and the form:
Class1 myClass = new Class1();
public Form1()
{
InitializeComponent();
label1.Text = myClass.number.ToString();
}
NO,
I think your form needs to access a reference to Class1 to use the data available in that, and not the other way around.
VERY seldomly a data class should instanciate a display form to display what it has to offer.
If the class is a data access layer of singleton, the form should reference that class, and not the other way around.
Based on the comments in your original post, here are a few ways to do it:
(this code is based on a Winform app in VS2010, there is 1 form, with a Label named "ValueLabel", a textbox named "NewValueTextBox", and a button.
Also, there is a class "MyClass" that represents the class with the changes that you want to publish.
Here is the code for the class. Note that I implement INotifyPropertyChanged and I have an event. You don't have to implement INotifyPropertyChanged, and I have an event that I raise whenever the property changes.
You should be able to run the form, type something into the textbox, click the button, and see the value of the label change.
public class MyClass: System.ComponentModel.INotifyPropertyChanged
{
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
public string AValue
{
get
{
return this._AValue;
}
set
{
if (value != this._AValue)
{
this._AValue = value;
this.OnPropertyChanged("AValue");
}
}
}
private string _AValue;
protected virtual void OnPropertyChanged(string propertyName)
{
if(this.PropertyChanged != null)
this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
Example 1: simple databinding between the label and the value:
So this time, we will just bind the label to an instance of your class. We have a textbox and button that you can use to change the value of the property in MyClass. When it changes, the databinding will cause the label to be update automatically:
NOTE: Make sure to hook up Form1_Load as the load event for hte form, and UpdateValueButton_Click as the click handler for the button, or nothing will work!
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private MyClass TheClass;
private void Form1_Load(object sender, EventArgs e)
{
this.TheClass = new MyClass();
this.ValueLabel.DataBindings.Add("Text", this.TheClass, "AValue");
}
private void UpdateValueButton_Click(object sender, EventArgs e)
{
// simulate a modification to the value of the class
this.TheClass.AValue = this.NewValueTextBox.Text;
}
}
Example 2
Now, lets bind the value of class directly to the textbox. We've commented out the code in the button click hander, and we have bound both the textbox and the label to the object value. Now if you just tab away from the textbox, you will see your changes...
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private MyClass TheClass;
private void Form1_Load(object sender, EventArgs e)
{
this.TheClass = new MyClass();
// bind the Text property on the label to the AValue property on the object instance.
this.ValueLabel.DataBindings.Add("Text", this.TheClass, "AValue");
// bind the textbox to the same value...
this.NewValueTextBox.DataBindings.Add("Text", this.TheClass, "AValue");
}
private void UpdateValueButton_Click(object sender, EventArgs e)
{
//// simulate a modification to the value of the class
//this.TheClass.AValue = this.NewValueTextBox.Text;
}
Example 3
In this example, we won't use databinding at all. Instead, we will hook the property change event on MyClass and update manually.
Note, in real life, you might have a more specific event than Property changed -- you might have an AValue changed that is only raised when that property changes.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private MyClass TheClass;
private void Form1_Load(object sender, EventArgs e)
{
this.TheClass = new MyClass();
this.TheClass.PropertyChanged += this.TheClass_PropertyChanged;
}
void TheClass_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "AValue")
this.ValueLabel.Text = this.TheClass.AValue;
}
private void UpdateValueButton_Click(object sender, EventArgs e)
{
// simulate a modification to the value of the class
this.TheClass.AValue = this.NewValueTextBox.Text;
}
}
There's no reason why you can't have multiple instances of a form, but in this case you want to pass the Class1 instance to the form you have. The easiest way is to add a property to Form1 and have that update the label text:
public class Form1 : Form
{
public Class1 Data
{
set
{
this.label.Text = value.LabelText;
}
}
}
Events and delegates are what you want to use here. Since you tagged this as beginner, I will leave the implementation as an exercise :), but here is the general idea:
Declare an event/delegate pair in your data class.
Create a method in your form to bind to the event.
When "something" happens in your data class, fire the event
The form's method will be invoked to handle the event and can update widgets appropriately
Good luck.