Control timer in form 1 from form 2, C# - c#

A label in form is displaying the count of timer. Now i want to stop,start and reset it using form 2. How can i do this.plz help

Forms are just classes, and the timer on Form 2 is an object inside that class.
You can change the Modifiers property of your timer to public, and then instantiate Form 2 inside Form 1, call the Show() method of Form 2, and then access your timer object which is now public.
So you have a project with 2 forms like so:
Create a button in Form 1 like so:
Place a timer object on Form 2 and change the access modifier like so:
Then put the following code under your button in form one:
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.Show();
f2.timer1.Enabled = true;
}
Now you can launch form 2 and access all of the properties on the timer on form 2 from form 1.
Does this help?

If the timer object resides in Form1, then create a public property for it:
public Timer Form1Timer { get { return timer1; } }
Then you can access this timer by having a reference to Form 1 in Form 2. You can do this by passing it in to the constructor, or having a set property on Form2. Once you have a reference to Form1, you can simply call methods on the timer:
Form1.Form1Timer.Start();
You can always create a singleton out of Form1 if you cannot pass a reference of it to Form2.
Declare your singleton:
private static Form1 _singleton
Initialize your singleton if it isnt already, and return it:
public static Form1 Singleton
{
get { _singleton ?? (_singleton = new Form1()); }
}
For best practices, make your Form1 constructor private. This of course will not work if Form1 does not have a default constructor (parameterless).
Then in Form2:
Form1.Singleton.Form1Timer.Start();

Do this
static Form1 _frmObj;
public static Form1 frmObj
{
get { return _frmObj; }
set { _frmObj = value; }
}
On Form load
private void Form1_Load(object sender, EventArgs e)
{
frmObj= this;
}
Access form and it's controls from another form
Form1.frmObj.timer1.Stop();

Related

How to access chart property of Form2 from Form1 by clicking button action of Form1 in C# [duplicate]

I am trying to understand whats the difference between a static and public properties. But when I tried to access my public property 'Test' in other form it says 'null'.
Heres Form1:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private string _test;
public string Test
{
get { return _test; }
set { _test = value; }
}
private void Form1_Load(object sender, EventArgs e)
{
_test = "This is a test";
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
frm2.Show();
}
}
Here's Form2:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
Form1 frm1 = new Form1();
label1.Text = frm1.Test;
}
}
To check the value of 'Test' in Form1, I put a breakpoint to this line:
label1.Text = frm1.Test;
But the value is 'null'.
Please help me how can I access public properties to other forms.
And BTW I tried to make this public property be a 'public static'. I can access this using this:
Form1.Test
But I noticed that I can change 'Test' value from Form2 which I don't want to happen. That's why I am trying to use public property but with no luck. Can somebody clarify me these things. Thanks for all your help guys!
EDIT: (For follow up question)
Sir John Koerner's answer is the best answer for my question. But I have a follow up question, I tried to make these 'test' properties to be a 'static', and I noticed that even if I make this property a static or public property, it still can be edit in Form2. To make myself clear here's a sample:
public partial class Form2 : Form
{
private Form1 f1;
public Form2(Form1 ParentForm)
{
InitializeComponent();
f1 = ParentForm;
}
private void Form2_Load(object sender, EventArgs e)
{
label1.Text = f1.Test;
}
private void button1_Click(object sender, EventArgs e)
{
f1.Test = "This test has been changed!";
this.Close();
}
}
After Form2 closed, I tried to break again in Form1_Load to check value of 'Test', and it was changed! How can I make a public property in Form1 to readOnly in Form2 and cannot be editted? Please clarify to me. Thanks a lot guys!
Your property is an instance variable, so the value can be different across different instances of Form1.
If you are trying to access instance variables from a parent form, the easiest way to do that is to pass Form1 in to the constructor of Form2.
public partial class Form2 : Form
{
private Form1 f1;
public Form2(Form1 ParentForm)
{
InitializeComponent();
f1 = ParentForm;
}
private void Form2_Load(object sender, EventArgs e)
{
label1.Text = f1.Test;
}
}
Then when you create a new Form2 from Form1, you can do this:
Form2 frm2 = new Form2(this);
If you want your property to be read only, you can simply not specify a setter:
public string Test
{
get { return _test; }
}
Use of this method 'static'
At first Control label property Modifiers=Public
in Program code below
public static Form1 frm1 = new Form1();
public static Form2 frm2 = new Form2();
in Form1 code below
Program.frm2.show();
in Form2 code below
label1.Text=Program.frm1.text;
The frm1 not your main form object. It is newly created object where property Test initializes when it loads (in Form1_Load event handler).
The first instance of Form1 shows an instance of Form2, and then Form2 creates another instance of Form1. This could work, but you set _test in the Form.Load event, which:
Occurs before a form is displayed for the first time.
You do not show the instance of Form1 you're trying to read Test from, so its Load event will not occur and Test remains null.
You could add a constructor overload or property to pass the Form1 reference as #JohnKoerner mentions, but I would prefer to only pass the required variable, perhaps even encapsulated in an event, to reduce coupling. Form2 usually doesn't need to know all about Form1.
public
The type or member can be accessed by any other code in the same assembly or another assembly that references it.
static
The static modifier on a class means that the class cannot be instantiated, and that all of its members are static. A static member has one version regardless of how many instances of its enclosing type are created.
A static class is basically the same as a non-static class, but there is one difference: a static class cannot be externally instantiated. In other words, you cannot use the new keyword to create a variable of the class type. Because there is no instance variable, you access the members of a static class by using the class name itself.
However, there is a such thing as a static constructor. Any class can have one of these, including static classes. They cannot be called directly & cannot have parameters (other than any type parameters on the class itself). A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced. Looks like this:
static class Foo()
{
static Foo()
{
Bar = "fubar";
}
public static string Bar { get; set; }
}
Static classes are often used as services, you can use them like so:
MyStaticClass.ServiceMethod(...);

Fully access a control from another Form

I have a main Windows Form (From1) which has a TextBox in it. I've also created another Windows Form (FindReplaceForm) which I'm going to use for implementing a form of find and replace dialog. I need to fully access all the properties and methods of my textbox in From1 from FindReplaceForm window.
Although I set the Modifiers property of my TextBox to Public, in FindReplaceForm window I can't access the text in it.
You can access the the owner form in the child using:
((Form1)Owner).textBox1.Text = "blah";
Assuming you have called your the child form using:
Form2 form = new Form2();
form.Show(this);
You need to pass a reference to the control or the form to your constructor so that you can reference the instance of the class. Add an argument of the same type as the calling form to the constructor:
private Form1 calling_form;
public FindReplaceForm (Form1 calling_form)
{
this.InitializeComponent()
this.calling_form = calling_form;
}
Then in your button call you can say:
calling_form.TextBox_value_text.SelectedText = "";
In your code, Form1 is a CLASS, not a variable. When you show your FindReplaceForm you should specify the Owner (just use this).
Now you can the Owner property on FindReplaceForm to get access to Form1.
Showing FindReplaceForm:
FindReplaceForm.Show(this);
In your button click event:
void Buttton1_Click(object sender, EventArgs e)
{
((Form1)this.Owner).TextBox_value_text.SelectedText = "";
}
Even if you set the textbox access modifier back to private, you can simply pass a reference to the textbox in the second form's constructor, thus enabling the second form to manipulate any property of the textbox:
first form:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm = new Form2(this.textBox1);
frm.Show();
}
}
second form:
public partial class Form2 : Form
{
private TextBox _OwnerTextBox;
public Form2(TextBox ownerTextBox)
{
InitializeComponent();
_OwnerTextBox = ownerTextBox;
this.textBox1.Text = _OwnerTextBox.Text;
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
_OwnerTextBox.Text = this.textBox1.Text;
}
}
In your FindReplaceForm.button1_Click function you want to control an object of class Form1. The error in your code explains that you don't call a function of an object of class Form1, but a function of class Form1 itself. The latter can only be done on static functions
You describe that you have an existing Form1 object and that your FindReplaceForm needs to change Form1 by calling functions in Form1. Probably there might be more than 1 Form1 object. Therefor your FindReplaceForm instance somehow needs to know which Form1 object it needs to control. Someone needs to tell this to your FindReplaceForm. This is usually done using the constructor of the FindReplaceForm or using a property.
public class FindReplaceForm
{
private Form1 formToControl = null;
public FindReplaceForm(Form1 formToControl)
{
this.formToControl = formToControl;
}
private void OnButton1_Click(...)
{
this.formToControl.TextBox_Value_Text.SelectedText = ...
}
Another method would be not to put the formToControl in the constructor, but as a property that you can set separately. Both methods have their advantages:
via constructor: your FindReplaceForm knows for sure there is alway a formToControl. The only place you have to check if formToControl really exists is in the constructor.
Using a default constructor with a separate FormToControl property may cause run time errors if people forget to set the FormToControl.
If you have a lot of properties, or some properties may have default values, or may be changed later, then the property method is more flexible.

Use information from objects in a child form from a main form in C#

I have a C# form called Form1.cs. By pressing a button, a new Form called Form2.cs comes up and I do something in form2. I have some variables in both forms.
I want to communicate between these two forms like this.
in form1:
string s=frm2.textbox1.text;`
form2:
if(frm1.checkbox1.checked==true)
or something like these codes.
I have tried the below code:
form1:
Form2 f=new Form2(this);
f.showDialog();`
form2:
private Form1 mainForm = null;
public Form2(Form callingForm)
{
mainForm = callingForm as Form1;
InitializeComponent();
}
`
and this works. But I don't want to use pointers like "this" and call this.mainform. Is there another way to communicate between forms like function calls?
Thank you.
Here are a couple of different approaches you can take that remove the need for Form 2 to know about Form 1 and that will make Form 2 reusable:
Delegates
You can declare a delegate function on the second form, and then pass a delegate method from the first form to the second one, so the second form can call back to the first one.
That approach means your second form no longer has any direct knowledge of your first form. It also means you can reuse the second form from any form and just pass in a delegate with the correct signature. Example below:
Form1:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 f=new Form2(UpdateTextBox);
f.ShowDialog();
}
private void UpdateTextBox(string newText)
{
label1.Text = newText;
}
}
Form 2:
public partial class Form2 : Form
{
public delegate void ChoiceMadeOnForm2Delegate(string choice);
private ChoiceMadeOnForm2Delegate _choiceDelegate;
public Form2(ChoiceMadeOnForm2Delegate choiceDelegate)
{
InitializeComponent();
_choiceDelegate = choiceDelegate;
}
private void saveButton_Click(object sender, EventArgs e)
{
_choiceDelegate(textBox1.Text);
Close();
}
}
In this example the delegate method just has one parameter, but if you want to pass back a series of values to Form 1 your delegate method declaration could include more parameters, or the parameter could be a class instead.
If you also want to set initial values for Form2 from Form 1 you can of course add those as constructor parameters for Form 2 and pass them in when you new up Form 2.
In your example Form 2 is shown as a dialog, but if you ever want to not show Form 2 modally you could even have a delegate on Form 1 that you pass to Form 2, so the forms can then communicate in two directions.
Use data binding and a shared class
Another approach is to use databinding, whereby you bind both forms to the same object and pass that object from Form 1 to Form 2 in its constructor when you open Form 2. When either form then changes the object those changes will then be reflected on both forms simultaneously and instantly.
To do that you need to read up on a concept called databinding and implement the INotifyPropertyChanged interface on the data class. You then bind the relevant controls on both forms to that class. Documentation on INotifyPropertyChanged can be found here
You can pass only information that Form2 needs and expose only information that Form1 needs
Form1
string valueOfForm2 = null;
using Form2 f = new Form2(this.checkbox1.Checked)
{
f.ShowDialog();
valueOfForm2 = f.ReturnValue;
}
Then use valueOfForm2 for you needs in the Form1
Form2
bool _IsForm1ValueChecked;
//By this property text will be exposed to outside of Form
public string ReturnValue { get { return this.textbox1.Text;} }
public Form2(bool isForm1ValueChecked)
{
_IsForm1ValueChecked = isForm1ValueChecked;
}
_IsForm1ValueChecked will be set in the contructor - then use it for your purpose in the Form2
I think for such stuff, I was using properties.
I prefer not access from one form the controls of the other one.
If I need information from one form, I prefer giving the access to this other form through properties.
More than that, you can define an interface that will contain all the properties/methods that you need for the communication between the forms. It will be clearer to work with an interface, you will get the information you need and won't be overloaded with other irrelevant information.
For example:
Interface IForm2
{
// your properties
string PersonName {get;} // Just an example
// your methods
}
class Form1: Form
{
private IForm2 _form2;
void Foo()
{
var pname = _form2.PersonName; // Just an example
}
}
class Form2: Form, IForm2
{
string PersonName
{
get
{
return personNameTextBox.Text;
}
}
}

Make method and control accessible to other class

I have my Form1 and my Form2.
My Form1 has a method which access a method that adds nodes to it's TreeView :
private void AddNode(TreeNode node)
{
treeView1.Nodes.Add(node);
}
I want to access this method from my Form2 but i'm kind of stuck at the fact that
A static AddNode method will require a static treeView1 which is kind of a bad practice.
A new instance of Form2 inside Form1 will create a different instance of treeView1 which is not what I want.
Also the treeView1 is declared inside the designer so I can't really change it's modifier to static ( I've been told it's not a good idea to put static controls inside your form).
Any Idea how I can do this ?
I think the best option is creating event in Form2 and subscribe to that event in Form1. When you do something on Form2 (e.g. user clicks button) raise that event (also you can pass some parameters as event argument).
Form1:
private void StartForm2Button_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2();
form2.SomethingHappened += Form2_SomethingHappened;
form2.Show();
}
private Form2_SomethingHappened(object sender, EventArgs e)
{
Form2 form2 = (Form2)sender;
string data = form2.Data;
// create node
AddNode(node);
}
Form2:
public event EventHandler SomethingHappened;
public string Data
{
get { return textBoxData.Text; }
}
private void SomeButton_Click(object sender, EventArgs e)
{
if (SomethingHappened != null)
SomethingHappened(this, EventArgs.Empty);
}
Update thus you saying, that forms created from two other different forms, then you need some other way to subscribe to Form2 event. You can get form2 from application opened forms collection. OR you can share some common object between forms:
public class Model
{
public event Action<string> DataAdded; // subscribe to this event in form1
public void AddData(string data) // call this method in form2
{
if (DataAdded != null)
DataAdded(data);
}
}
Well, in best world, I'd created a model, which will have all data, and just reflected that model state on Form1.
Below are some options that require a reference to be stored somewhere. This may not be the best option for the situation (or it may be depending on your situation) but there are other alternatives posted too so take your pick.
One solution is you can just have a static reference to the Form1 instance that you want to use.
static Form1 OpenForm1 = new Form1();
//in some other code
OpenForm1.MyFunction();
There are many other ways, the main point is your need to ensure your Form2 instance has a reference to your Form1 instance somehow.
Another option, you can pass the instance when you create Form2:
as a property for example...
//create Form2 from some where else
Form2 form2 = new Form2();
form2.ReferenceToForm1 = form1;
//in form2
public Form1 ReferenceToForm1 {get;set;}
//when needed in form2
ReferenceToForm1.MyFunction();
Declare an interface and pass form2 a reference to something that implements the interface.
Eg:
public interface INodeAddable {
void AddNode(TreeNode node);
}
public class Form1 : INodeAddable
{
private void SomeMethod()
{
var f2 = new Form2(this);
}
public void AddNode(TreeNode n)
{
// add node to tree
}
}
public class Form2
{
private INodeAddable x;
public Form2(INodeAddable x)
{
this.x = x;
}
public void SomeEventHandler(object sender, EventArgs e)
{
x.AddNode(someNewNode);
}
}
Make the forms able to access one another.
Since you said that they are generated from different forms, one approach would be to have the common root have knowledge of their existence and make the connection from their common ancestor.
The best approach i can think of, if this kind of behavior is something you will encounter in the future is to have a basic EventAggregator that is injected into all forms, and through that you can have messages passed from one to another without having them tightly coupled. With that you can have Form1 subscribe to an event that Form2 triggers and when that event is triggerd you would add the node.

How do I refrence form1 from form2 without causing an infinite loop?

In my main form (form1) I have checkboxes that when checked should also check the corresponding box in form2. I also want if checkboxes in form2 are checked they check the corresponding boxes on form1. The problem that I believe I am encountering is that form1 can make an object of form2 to reference, however if I instantiate an object of form1 within form2 I believe it creates an infinite loop? Any help figuring this out is appreciated.
Form1 creates an object of form2:
Form2 formSettings = new Form2();
Now when I have an event I can update form2:
public void logScanResultsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (logScanResultsToolStripMenuItem.Checked)
{
formSettings.chbxLogScanResults.Checked = true;
}
else
{
formSettings.chbxLogScanResults.Checked = false;
}
}
But if I try to do something similar in Form2:
Form1 form1 = new Form1();
So that I can reference form1's menu item from within form2(formSettings) I end up creating an object (form1) that calls to make an object of Form1, which within Form1 includes a call to create an object of Form2 and thus an endless loop.
You shouldn't create an instance every time a checkbox is checked off. You need to maintain the instances alive and hide/show them as needed. Also, the constructor of one of the forms should receive the other one as parameter in its constructor so they can reference each other.
Hopefully this is clear enough. It isn't a straight out answer as you really dont have much detail in your question.
Basically you have two forms, Form1 and Form2, which will be throwing events (OnChangeEvent?) on the change of some checkboxes.
Form1 listens for events from Form2 and Form2 does the same from Form1.
If Form1's event listen receives a OnChangeEvent and changes its checkbox then it should raise an OnChangeEvent. If on the other hand it doesn't change its checkbox (as it already has the correct value) then it should not raise an OnChangeEvent.
In the body of Form1 you need to declare Form2 to hold an instance of it for referencing and to open it. When you call the Form2.Show method from Form1, you will pass a reference of itself to Form2 which you then can use to gain access back to Form1.
public partial class Form1 : Form
{
Form2 form2 = new Form2();
public Form1()
{
InitializeComponent();
}
private void form1Button_Click(object sender, EventArgs e)
{
form2.Show(this);
}
private void form1CheckBox_CheckedChanged(object sender, EventArgs e)
{
form2.ChangeCheck(form1CheckBox.Checked);
}
public void ChangeCheck(bool isItChecked)
{
form1CheckBox.Checked = isItChecked;
}
}
In Form2 you can now reference Form1 as the owner.
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void form2CheckBox_CheckedChanged(object sender, EventArgs e)
{
((Form1)this.Owner).ChangeCheck(form2CheckBox.Checked);
}
public void ChangeCheck(bool isItChecked)
{
form2CheckBox.Checked = isItChecked;
}
}

Categories