I have two Form classes, one of which has a ListBox. I need a setter for the SelectedIndex property of the ListBox, which I want to call from the second Form.
At the moment I am doing the following:
Form 1
public int MyListBoxSelectedIndex
{
set { lsbMyList.SelectedIndex = value; }
}
Form 2
private ControlForm mainForm; // form 1
public AddNewObjForm()
{
InitializeComponent();
mainForm = new ControlForm();
}
public void SomeMethod()
{
mainForm.MyListBoxSelectedIndex = -1;
}
Is this the best way to do this?
Making them Singleton is not a completely bad idea, but personally I would not prefer to do it that way. I'd rather pass the reference of one to another form. Here's an example.
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;
}
}
(source: ruchitsurati.net)
(source: ruchitsurati.net)
Access the form's controls like this:
formname.controls[Index]
You can cast as appropriate control type, Example:
DataGridView dgv = (DataGridView) formname.Controls[Index];
I usually use the Singleton Design Pattern for something like this http://en.wikipedia.org/wiki/Singleton_pattern . I'll make the main form that the application is running under the singleton, and then create accessors to forms and controls I want to touch in other areas. The other forms can then either get a pointer to the control they want to modify, or the data in the main part of the application they wish to change.
Another approach is to setup events on the different forms for communicating, and use the main form as a hub of sorts to pass the event messages from one form to another within the application.
It's easy, first you can access the other form like this:
(let's say your other form is Form2)
//in Form 1
Form2 F2 = new Form2();
foreach (Control c in F2.Controls)
if(c.Name == "TextBox1")
c.Text = "hello from Form1";
That's it, you just write in TextBox1 in Form2 from Form1.
If ChildForm wants to access the ParentForm
Pass ParentForm instance to the ChildForm constructor.
public partial class ParentForm: Form
{
public ParentForm()
{
InitializeComponent();
}
public string ParentProperty{get;set;}
private void CreateChild()
{
var childForm = new ChildForm(this);
childForm.Show();
}
}
public partial class ChildForm : Form
{
private ParentForm parentForm;
public ChildForm(ParentForm parent)
{
InitializeComponent();
parentForm = parent;
parentForm.ParentProperty = "Value from Child";
}
}
There is one more way, in case you don't want to loop through "ALL" controls like Joe Dabones suggested.
Make a function in Form2 and call it from Form1.
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
public void SetIndex(int value)
{
lsbMyList.SelectedIndex = value;
}
}
public partial class Form1 : Form
{
public Form2 frm;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
frm=new Form2();
frm.Show();
}
private void button1_Click(object sender, EventArgs e)
{
frm.SetIndex(Int.Parse(textBox1.Text));
}
}
Here's also another example that does "Find and Highlight". There's a second form (a modal) that opens and contains a textbox to enter some text and then our program finds and highlights the searched text in the RichTextBox (in the calling form). In order to select the RichTextBox element in the calling form, we can use the .Controls.OfType<T>() method:
private void findHltBtn_Click(object sender, EventArgs e)
{
var StrBox = _callingForm.Controls.OfType<RichTextBox>().First(ctrl => ctrl.Name == "richTextBox1");
StrBox.SelectionBackColor = Color.White;
var SearchStr = findTxtBox.Text;
int SearchStrLoc = StrBox.Find(SearchStr);
StrBox.Select(SearchStrLoc, SearchStr.Length);
StrBox.SelectionBackColor = Color.Yellow;
}
Also in the same class (modal's form), to access the calling form use the technique mentioned in the #CuiousGeek's answer:
public partial class FindHltModalForm : Form
{
private Form2 _callingForm = null;
public FindHltModalForm()
{
InitializeComponent();
}
public FindHltModalForm(Form2 CallingForm)
{
_callingForm = CallingForm;
InitializeComponent();
}
//...
Related
I have two Windows Form in project C#.
public partial class Form1 : Form
{
public void add(){
//
}
}
public partial class FormAdd : Form
{
//
}
In Form1 after button click I open FormAdd:
var form = new FormAdd();
form.Show();
After in FormAdd I try to call parent method add:
Form1 f = new Form1();
f.add();
But I can not get access to any methods and properties of parent form.
I get error:
One approach is to pass Form1 in as the Owner of your FormAdd instance in the Show() call:
public partial class Form1 : Form
{
private void button1_Click_1(object sender, EventArgs e)
{
var form = new FormAdd();
form.Show(this); // pass this instance of Form1 in as the Owner of our FormAdd instance
}
}
Now, over in FormAdd, cast the Owner property to Form1 and call add():
public partial class FormAdd : Form
{
private void button1_Click(object sender, EventArgs e)
{
if (this.Owner is Form1)
{
Form1 f1 = (Form1)this.Owner;
f1.add();
}
}
}
Based on your picture, try to add the code above one bracket. Since the error seems to be on the scope of your condition.
This should look like this:
else
position = 0;
//{ <-- Remove this and put it below
if (this.Owner is Form1)
{
//TODO:
}
} //This should be here
Everything should compile properly after that.
I am new to c#. I have the following in my project in windows forms:
Form1 with button and DataGridView.
Form2 with button.
Form3 with button and 3 textBoxes.
As shown in the screenshot In form1, I click buttonOpenForm2 form2 pops up. Then in form2 I click buttonOpenForm3 form3 pops up which has 3 text boxes and button. Now the 3 forms are open.
I enter values in textBox1, textBox2 and textBox3 and when click buttonAddRow ( from form3) I want these values to be inserted into the DataGRidView in Form1.
My question is:
How can I add a row into DataGridView in Form1 ( parent) from form3 (child of child form) WITHOUT closing form2 and form3? I mean I want to pass the data while form2 and form3 are still open.
Please help me. Thank you
Form1:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void buttonOpenForm2 _Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
frm2.Show();
}
}
Form2:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void buttonOpenForm3 _Click(object sender, EventArgs e)
{
Form3 frm3 = new Form3();
frm3.Show();
}
}
Form3:
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
private void buttonAddRow _Click(object sender, EventArgs e)
{
//What to write here to insert the 3 textboxes values into DataGridView?
}
}
You cannot expect to get complete code that's ready to be pasted. I quickly wrote this in notepad to give you idea about how events work best in such cases. I assumed Form1 directly opens Form3. Solution below shows how to use events.
You home work is to make it work by adding another form Form2 in between. You can do so by propagating same event via Form2 which sits in middle.
Form3.cs
public partial class Form3 : Form
{
public event EventHandler<AddRecordEventArgs> RecordAdded
public Form3()
{
InitializeComponent();
}
private void buttonAddRow _Click(object sender, EventArgs e)
{
OnRecordAdded();
}
private void OnRecordAdded() {
var handler = RecordAdded;
if(RecordAdded != null) {
RecordAdded.Invoke(this, new AddRecordEventArgs(txtQty.Text, txtDesc.Text, txtPrice.Text))
}
}
}
AddRecordEventArgs.cs
public class AddRecordEventArgs : EventArgs
{
public AddRecordEventArgs(string qty, string desc, string price) {
Quantity = qty;
Description = desc;
Price = price;
}
public int Quantity { get; private set; }
public string Description { get; private set; }
public decimal Price { get; private set; }
}
Form1.cs
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void buttonOpenForm3_Click(object sender, EventArgs e)
{
Form3 frm3 = new Form3();
frm3.RecordAdded += Form3_RecordAdded;
frm3.Show();
}
private void Form3_RecordAdded(object sender, AddRecordEventArgs e) {
// Access e.Quantity, e.Description and e.Price
// and add new row in grid using these values.
}
}
1 Solution
You can use pattern with sending data further by constructor (special setter before Show method) and getting them back after window is closed by public getter.
public partial class Form2 : Form
{
Data Data1 {get; set;}
//Instead of Data you can pass Form1 class as parametr.
//But this might lead to unreadable code, and using too mutch methods and fields that could be private, public
public Form2(Data data)
{
InitializeComponent();
Data1 = data;
}
private void buttonOpenForm3 _Click(object sender, EventArgs e)
{
//Repeat pattern
Form3 frm3 = new Form3(Data1);
frm3.Show();
}
}
Optionally you dont have to call 3rd window constuctor. Just create Instance of third window store it in first form and just Show it by calling first instance you passed with data. But this might be bad practice in larger scale.
2 Solution
You can use singleton pattern. Create Instance of an first form inside constructor of first form and use it in third form. But you would need to ensure that there will be no more then one and always one instance of this object in memory.
You can pass owner to method Show() for new forms. Then you can get owner form from Owner property.
private void buttonOpenForm2 _Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
frm2.Show(this);
}
So you can get Form1:
(Form1)frm2.Owner
and call public method of Form1 class and pass there your new data.
I have two forms, Form1 and Form2. Form1 has a variable int x. When the program is executed, Form1 is hidden and Form2 is shown; however i need to call the variable from the existing Form1.
I know the method to call the variable by calling a new instance of Form1.
Form1 r = new Form1();
r.x = 20;
But I want to know how to do it for an already opened Form1.
Take several cases, like if there are multiple variables that are called from Form1, by several forms (Form2, Form3, Form4 etc...). Any variable can be called from Form1 by the forms. Also, forms can call variables from other forms (Like if Form1 and Form2 is open, then Form3 can call variables from Form1 AND Form2)
I know its a huge list, but would really appreciate if anyone can find a good way to implement it.
You will have to have a reference to the "already opened" form1 instance, so that you can reference the value of x on that form.
So, lets say that Form2 instantiates the hidden form1. You will have to have a reference in form2 to the form1, to reference the variable.
OK, Lets say this is the code for form2
public partial class Form2 : Form
{
private Form1 f;
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
f = new Form1
{
Visible = false
};
int x = f.X;
}
}
and then code for form1
public partial class Form1 : Form
{
public int X { get; set; }
public Form1()
{
InitializeComponent();
X = 20;
}
}
and you need to ensure that the form luanched from the program class is
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form2());
}
}
You can do it in following ways,
in my case form1 is form4 and form2 is form5. please consider, :)
//code on form4:
// this is by passing the reference of the form to other form
public partial class Form4 : Form
{
public int a { get; set; }
public int b { get; set; }
public Form4()
{
InitializeComponent();
}
private void Form4_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
a = 5;
b = 6;
Form5 frm5 = new Form5();
frm5.frm4 = this;
this.Close();
frm5.Show();
}
}
// code on form5
public Form4 frm4 { get; set; }
private void Form5_Load(object sender, EventArgs e)
{
int x = frm4.a;
int y = frm4.b;
}
Also you can have a class file in which the instance of the form1 will be static, so that you can use that instance on form2 to refer to the form1's properties.
Let me know, if it does not solve your problem.
I hope it will help you. :)
Create a public property on the form itself. Have the get accessor return the form value. You can call it like this. Form1.MyProperty;
public string MyPrperty {
get {
return Form1.txtExample.text;
}
}
EDIT:
You can return a dictionary of all of those values if you have that many to return at a time. I would seriously consider rethinking your form if you have 20-40 values being filled. That sounds like a poor user experience to me.
i think there is a reason that you wouldn't try System.Properties.Settings.Default
accessible from Project Menu --> Properties in visual studio...
Thanks...
My guess is that you are looking for System.Windows.Forms.Application.OpenForms property which holds all the open forms in an array.
What you need to do is to check the type of each form and if it is equivalent to Form1 access the variable's value. Also, to access the variable outside the form you need to set its access modifier to either Public or make a corresponding property for it.
EDIT
Here is a sample code: (untested)
public partial class Form1 : Form
{
public int X;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
X = 100;
Form2 frm = new Form2();
frm.Show();
this.Hide();
}
}
public partial class Form2 : Form
{
int local_X = 0;
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
foreach(Form f in System.Windows.Forms.Application.OpenForms)
{
if(typeof(f) == typeof(Form1))
{
local_X = f.X; // access value here and set in local variable
}
}
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Value of X is : " + local_X); // Show alert for value of variable on button click
}
}
EDIT
Or you can use constructor overloading to accomplish this task:
public partial class Form1 : Form
{
public int X;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
X = 100;
Form2 frm = new Form2(x); // pass variable to form2, if multiple values pass int array
frm.Show();
this.Hide();
}
}
public partial class Form2 : Form
{
int local_X = 0;
public Form2()
{
InitializeComponent();
}
// Overloading of constructor
public Form2(int X) // if multiple values pass int array
{
InitializeComponent();
local_X = x; // capture value from constructor in class variable.
}
private void Form2_Load(object sender, EventArgs e)
{
// no need to iterate here for now due to overloading value get passed during initialization.
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Value of X is : " + local_X); // display value if alert box.
}
}
Let's look at the situation.You have multiple forms in your application and you want to do access several variables these forms.
My guess is,
public static class GlobalVariables
{
public static object MyVariable1 { get; set; }
public static object MyVariable2 { get; set; }
}
So you can access variables everywhere in your project.
It doesn't matter whether which form is opened or closed. Your ultimate goal is to access a member from Form1 in Form2 isn't it? If that is the case when you create an instance of your Form2, do it like this
Form1 objForm1 = new Form1();
Form2 obj = new Form2(objForm1);
so that in form 2 class looks like this
class Form2: Form
{
private Form1 form1Object;
public Form2(Form1 obj)
{
form1Object = obj;
}
private void SomeMethodInForm2()
{
//Here you can access the variable in form1 like
form1Object.PropertyNameYouWantToAccess;
}
}
The form 1 class can look like this
class Form1: Form
{
public int PropertyNameYouWantToAccess{get;}
}
In my app in several time i have to call a window(class). the work of this window is to show the meaning of a word.when i again call that window a new window shows but the previous one also shows.
I have two form named form1,form2.
Form1 is like that:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string a = textBox1.Text;
Form2 s = new Form2(a);// it will be called as many time as i click
s.Show();
}
}
Form2 is like that:
public partial class Form2 : Form
{
public Form2(string s)
{
InitializeComponent();
label1.Text = s;
}
}
what i want is that inside form1 if i call form2 it shows but if i call form2 again the previous form2 window will be closed automatically and new form2 window will be shown instead of previous one.
How can i do that????
Here's an example of storing the Form2 reference at class level, as mentioned by the others already:
public partial class Form1 : Form
{
private Form2 f2 = null;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (f2 != null && !f2.IsDisposed)
{
f2.Dispose();
}
string a = textBox1.Text;
f2 = new Form2(a);
f2.Show();
}
}
I think you should consider using singleton pattern.
You can implement it like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string a = textBox1.Text;
Form2.ShowMeaning(a);// it will be called as many time as you click
}
}
and Form2
public partial class Form2 : Form
{
private static readonly Form2 _formInstance = new Form2();
private Form2()
{
InitializeComponent();
}
private void LoadMeaning(string s)
{
label1.Text = s;
}
//Override method to prevent disposing the form when closing.
protected override void OnClosing(CancelEventArgs e)
{
e.Cancel = true;
this.Hide();
}
public static void ShowMeaning(string s)
{
_formInstance.LoadMeaning(s);
_formInstance.Show();
}
}
Hope it helps.
C# textbox sending text value. Situation, i got 2 forms. Form1 and Form2. Form1 got a textbox and form2 got a textbox and a button, i will put a text value on form2 textbox and when i click the form2 button the value of form2 textbox will be sent and change the form1 textbox value....Need help..
This is what ive done..im just gonna summarize it
Form1 got no codes just textbox1
This is the code in form2 button
private void change_Click(object sender, EventArgs e)
{
form1 frm1 = new form();
string test = textbox2.text
frm1.textbox.text = test;
}
ive try some poping message box to check if the value pass...and so far the value was really pass but no changes in the UI
Assuming you create Form2 as a child of Form1 (from within Form1, do something like Form2 from = new Form2();, you can access any public property of the child form from within the parent. So, just make sure to set the accessibility of the TextBox to public, and do something like this:
var form = new Form2();
form.ShowDialog();
this.TextBox1.Text = form.TextBox1.Text;
You can declare the textbox in Form1 to be public, then you can access it from form2 by going form1.textBoxName.propertyName
You could use events for this:
Define an interface:
public interface ITextChange
{
event EventHandler SomeTextChanged;
}
Then let you form with button implement this interface and fire the event on button click passing the value from the textbox as the first parameter:
public partial class Form1 : Form, ITextChange
{
public event EventHandler SomeTextChanged = delegate { };
public Form1 () {}
private void button1_Click(object sender, EventArgs e)
{
SomeTextChanged(textBox1.Text, null);
}
}
Pass an instance of this form to your second form like this:
public partial class Form2 : Form
{
public Form2(ITextChange f)
{
InitializeComponent();
f.SomeTextChanged += new EventHandler(f_SomeTextChanged);
}
void f_SomeTextChanged(object sender, EventArgs e)
{
textBox1.Text = sender.ToString();
}
}
So, when you create your Form2, you need to pass an instanse of Form1:
Form2 f = new Form2(form1);
As soon as you press the button, the textbox on the second form will automatically get the value.
P.S.: for more info, please, see Events Tutorial
You could rely on knowledge of Form1 in Form2 by making the TextBox public. But in my opinion the proper way to do it would to create a custom event handler, subscribe to it in Form2 and pass the text as a eventarg. Code adapted from this MSDN Article
Form1
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Form2 frm2 = new Form2();
frm2.RaiseCustomEvent+=new CustomEventHandler(frm2_RaiseCustomEvent);
frm2.Show(this);
}
void frm2_RaiseCustomEvent(object sender, CustomEventArgs a)
{
textBox1.Text = a.Message;
}
}
}
Form2
namespace WindowsFormsApplication1
{
public delegate void CustomEventHandler(object sender, CustomEventArgs a);
public partial class Form2 : Form
{
public event CustomEventHandler RaiseCustomEvent;
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
RaiseCustomEvent(this, new CustomEventArgs(textBox1.Text));
}
}
public class CustomEventArgs : EventArgs
{
public CustomEventArgs(string s)
{
msg = s;
}
private string msg;
public string Message
{
get { return msg; }
}
}
}
you could use the .Tag property (look at my question here
the simple way to do it is like this:
you said that the textBox.text in form2 would replace the texBox.text in form1 right?
do this in the form2
try
{
private void change_Click(object sender, EventArgs e)
{
form2 frm2 = new form();
frm2.Tag = this.textbox2.text;
frm2.ShowDialog();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
then write this when you load your form1
string myText = (string)this.Tag;
this.textbox1.text = myText;
The reason your form1.textbox1 was not updated because you initialized a new instance of form1
form1 frm1 = new form();
So to update the form1 you have on screen, you need to get its instance injected into the form2. For instance, when you show form2, you set.
form2.Form1 = currentForm1Instance;
Hope this helps.