I have a User control with a textbox. I want to pass the text from textbox on the User control back to the parent form, when the text changes.
I found the following code in my user control which work well for doing this. This includes a TextChanged event.
public string pub_callsign
{
get { return textBox1.Text; }
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
var textBoxContent = this.textBox1.Text;
var parent = this.Parent as form1;
parent.pub_callsign = pub_callsign;
}
In my parent form I have
public string pub_callsign
{
set { txtbx_callsign.Text = value; }
}
However I would like to use this User Control on more than 3 form,
So how do I get the form name from the form to the user control. Thereby what is shown below as form1 or form2 to be a variable containing the formname ??
var parent = this.Parent as form1;
var parent = this.Parent as form2;
var parent = this.Parent as formname_value;
hope this makes sense.
Dave
Add a property in the user control that gives you access to the text box contents.
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public string Contents { get => textBox1.Text; set => textBox1.Text = value; }
}
In the form use the property to read the contents of the text box
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void ReadContents()
{
var contents = userControl11.Contents;
}
}
You need to be able to have the user control tell the parent - no matter if the parent is a form or other user control - that the value of the text box has changed.
I created a user control called MyUserControl with a single text box called textBox1.
I added a TextBoxTextChanged event to MyUserControl and ended up with the following code:
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
InitializeComponent();
}
public event EventHandler<string> TextBoxTextChanged;
private void textBox1_TextChanged(object sender, EventArgs e)
{
this.TextBoxTextChanged?.Invoke(this, textBox1.Text);
}
}
Now, on Form1, I added the an instance of MyUserControl called myUserControl1 and added the handler for TextBoxTextChanged. I ended up with this code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void myUserControl1_TextBoxTextChanged(object sender, string e)
{
this.label1.Text = e;
}
}
When I run that the text in the user control is automatically updated in the label as I type.
Where do you want to put the text box text? If it's in the title bar, do this:
formName.Text = yourTextBox.Text;
If it's in a label or another text box, do the same thing but use the control with its text property, and set it to the text box's text property.
Related
I am new to c# and using windows forms.
I have Form1 with a button (Button_Save) and textbox . and I have user control1 with one button (button1).
What I am trying to do in this program is: when I click on button1, its text appear in textbox (in Form1), then I enter new text and click save, the button1 text change accordingly.
I will explain when the freeze happens:
There are 2 parts:
first part: when I created instance of user control1 in Form1 then I participated in UserControl1Event and run program it works fine and button1 text appears in textbox when I click on it. Second part when I create instance of Form1 in user control1 and participated in Form1Event and run the program the program freezes for long time then gives error pointing at Form1 instance in user control1 (as shown in screen shot).
Anyone knows why this is happening ? what I am doing wrong?
Form1:
public partial class Form1 : Form
{
public event EventHandler Form1Event;
UserControl1 uc1 = new UserControl1();
public Form1()
{
InitializeComponent();
Controls.Add(uc1);
uc1.Visible = true;
uc1.UserControl1Event += new EventHandler(Handleuc1);
}
string Return_TextBox_Txt;
public string TextBox_Txt
{
get { return Return_TextBox_Txt; }
}
public void Handleuc1(object sender, EventArgs e) ////////////Handle uc1 event
{
textBox1.Text = uc1.ButtonText;
}
private void button_save__Click(object sender, EventArgs e)//change button text
{
Return_TextBox_Txt = textBox1.Text;
Form1Event(this, e);
}
}
User Control1:
public partial class UserControl1 : UserControl
{
string BtnTxt;
Form1 frm1 = new Form1();
public event EventHandler UserControl1Event;
public string ButtonText
{
get { return BtnTxt; }
}
private void UserControl1_Load(object sender, EventArgs e)
{
frm1.Form1Event += new EventHandler(HandleForm1Event);
}
public void HandleForm1Event(object sender, EventArgs e)
{
button1.Text = frm1.TextBox_Txt;
}
private void Button1_Click(object sender, EventArgs e)
{
BtnTxt = button1.Text;
UserControl1Event(this, e);
}
}
The problem is that both of your classes depend on each other.
Form1, when created, creates an instance of UserControl1, which in turn creates and instance of Form1, and so on. All this chained creation eventually makes your code throw a StackOverflowException.
It's expected behavior because of you are creating new Form1 instance and on object constructing it creates new UserControl1 instance that also creates new Form1 instance and so on.
If you need to have an owner of UserControl1 inside its instance you can pass it to the UserControl1 constructor:
public partial class Form1 : Form
{
...
UserControl1 uc1;
public Form1()
{
InitializeComponent();
// creates new control and pass owner via constructor parameter
uc1 = new UserControl1(this);
Controls.Add(uc1);
uc1.Visible = true;
uc1.UserControl1Event += new EventHandler(Handleuc1);
}
...
}
public partial class UserControl1 : UserControl
{
Form1 frm1;
public UserControl1(Form1 owner)
{
// save user control owner passed from constructor parameter to local variable
frm1 = owner;
}
...
}
Ok, am going to try and ask this without sounding dumb. I have a user form that I create dynamic textboxes inside a panel. I want to reference these textboxes or the panel from another form to send the texbox data to excel. I need to know how I can reference these controls. Thank you in advance!!
Create public properties on the user control, one for each element you want to access.
public class MyControl : UserControl
{
public string Name
{
get { return textBoxName.Text; }
}
public string Address
{
get { return textBoxAddress.Text; }
}
...
Then use those from the parent control that hosts the user control.
string name = myControl1.Name;
string address = myControl.Address;
Assume you have Form1 that dynamically adds a TextBox to panel panel1 during the load event like this:
private void Form1_Load(object sender, EventArgs e)
{
panel1.Controls.Add(new TextBox());
}
And you have Form2 from which you want to access the data on panel1. On Form2 you can add a public field to store the reference to panel1, but you can call it whatever you want. In this case, I use sourcePanel:
public partial class Form2 : Form
{
public Panel sourcePanel;
public Form2()
{
InitializeComponent();
}
}
Then you can pass the panel1 reference to any new Form2 instance when the new instance is created, for example from a button click event on Form1:
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.sourcePanel = panel1;
f2.Show();
}
Then on Form2, you can access all the values in the TextBoxes with code like this:
private void Form2_Load(object sender, EventArgs e)
{
foreach (TextBox txt in sourcePanel.Controls.OfType<TextBox>())
{
System.Diagnostics.Debug.WriteLine(txt.Text);
}
}
I have 2 forms. The second form is opened from a method in the first form and I wish to be able to update the textbox that exists within that second form.
Basically I have the following code:
private void sendAllButton_Click(object sender, EventArgs e)
{
SendConsoleGUI sendOutGUI = new SendConsoleGUI();
sendOutGUI.Show();
sendOutGUI.sendConsoleTextBox.Text = "Test";
}
When I press the button the second form (SendConsoleGUI form) opens but "Test" is never added to its textbox.
Am I doing something wrong here?
You need to use invoke method.
sendOutGUI.Invoke((MethodInvoker) delegate { sendOutGUI.sendConsoleTextBox.Text = "Test"; });
public partial class ParentForm : Form
{
public ParentForm()
{
InitializeComponent();
}
private void sendAllButton_Click(object sender, EventArgs e)
{
SendConsoleGUI sendOutGUI = new SendConsoleGUI("Test");
sendOutGUI.Show();
}
}
public partial class ChildForm : Form
{
public ChildForm(string str)
{
InitializeComponent();
sendConsoleTextBox.Text = str;
}
}
This will work for you if you only wish to update it when the ChildForm is initially created.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
accessing controls on parentform from childform
I have parent form form1 and child form test1 i want to change label text of parent form from child form in my parent form i have method to showresult()
public void ShowResult()
{ label1.Text="hello"; }
I want to change label.Text="Bye"; form my child form test1 on button click event. Please give any suggestions.
when calling the child form, set the Parent property of child form object like this..
Test1Form test1 = new Test1Form();
test1.Show(this);
On your parent form, make the property of your label text like as..
public string LabelText
{
get
{
return Label1.Text;
}
set
{
Label1.Text = value;
}
}
From your child form you can get the label text like that..
((Form1)this.Owner).LabelText = "Your Text";
No doubt there are plenty of short cut ways to do this, but in my view a good approach would be to raise an event from the child form that requests that the parent form changes the displayed text. The parent form should register for this event when the child is created and can then respond to it by actually setting the text.
So in code this would look something like this:
public delegate void RequestLabelTextChangeDelegate(string newText);
public partial class Form2 : Form
{
public event RequestLabelTextChangeDelegate RequestLabelTextChange;
private void button1_Click(object sender, EventArgs e)
{
if (RequestLabelTextChange != null)
{
RequestLabelTextChange("Bye");
}
}
public Form2()
{
InitializeComponent();
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.RequestLabelTextChange += f2_RequestLabelTextChange;
}
void f2_RequestLabelTextChange(string newText)
{
label1.Text = newText;
}
}
Its a bit more long winded but it de-couples your child form from having any knowledge of its parent. This is a good pattern for re-usability as it means the child form could be used again in another host (that doesn't have a label) without breaking.
Try something like this:
Test1Form test1 = new Test1Form();
test1.Show(form1);
((Form1)test1.Owner).label.Text = "Bye";
I have a UserControl, that contains a panel, the panel contains a picture box.
When I MouseMove over the Picture Box, I want to update a label on the MainForm.
I have a get/set method on the main form, but how do I use it?? thanks
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
public String MouseCords
{
get { return this.MouseCordsDisplayLabel.Text; }
set { this.MouseCordsDisplayLabel.Text = value; }
}
}
public partial class ScoreUserControl : UserControl
{
public ScoreUserControl()
{
InitializeComponent();
}
private void ScorePictureBox_MouseMove(object sender, MouseEventArgs e)
{
// MainForm.MouseCords("Hello"); //What goes here?
}
}
Actually it's possible to do in your case like:
((MainForm)this.ParentForm).MouseCords = "Some Value Here";
But the right way is with events like Felice Pollano mentinoed:
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
this.myCustomControlInstanse.PicureBoxMouseMove += new EventHandler<StringEventArgs>(myCustomControlInstanse_PicureBoxMouseMove);
}
private void myCustomControlInstanse_PicureBoxMouseMove(object sender, StringEventArgs e)
{
this.MouseCordsDisplayLabel = e.Value // here is your value
}
}
public class StringEventArgs : EventArgs
{
public string Value { get; set; }
}
public partial class ScoreUserControl : UserControl
{
public event EventHandler<StringEventArgs> PicureBoxMouseMove;
public void OnPicureBoxMouseMove(String value)
{
if (this.PicureBoxMouseMove != null)
this.PicureBoxMouseMove(this, new StringEventArgs { Value = value });
}
public ScoreUserControl()
{
InitializeComponent();
}
private void ScorePictureBox_MouseMove(object sender, MouseEventArgs e)
{
this.OnPicureBoxMouseMove("Some Text Here");
}
}
Ideally, you should raise an event for the same.
Create a delegate
public delegate void Update();
in the user control
public class MyUserControl : UserControl
{
public event Update OnUpdate;
}
On the main form register a handler for the user controls event.
public class Main
{
public Main()
{
myUserControl.OnUpdate += new Update(this.UpdateHandler);
}
void UpdateHandler()
{
//you can set the delegate with sm arguments
//set a property here
}
}
On user control,
To raise an event on button click
do this
OnUpdate();
This might give you an idea...
public partial class ScoreUserControl : UserControl
{
public ScoreUserControl()
{
InitializeComponent();
}
private void ScorePictureBox_MouseMove(object sender, MouseEventArgs e)
{
// MainForm.MouseCords("Hello"); //What goes here?
MainForm parent = this.ParentForm as MainForm;
if (parent != null) parent.MouseCordsDisplayLabel.Text = "Hello";
}
}
You have several options:
Create an event on the user control and have to form listen to it (I think this is the recommended way by most C# programmers).
Pass a reference to the main form to the User Control (in the constructor). This way, the user control knows about its MainForm.
Cast this.ParentForm to the MainForm class, then you have the reference.
Options 2 and 3 are somewhat more comfortable and lazy, but the cost is that the user control has to know about the specific class MainForm. The first option has the advantage that you could reuse the user control in another project, because it does not know about the MainForm class.
You should publish an event from the user control and subscribe to it from the main form.
At least this is the pattern suggested for winform. In any case the idea is to make the control "observable" from the agents who need to see the coords, instead of using it as a driver to update the interested agents.