Access object from another class - c#

I'm trying to change the interval value of a timer (in Form1) from my settings form.
I'm declaring the form1 with static Form1 formInstance;
But it throws null exception on forminstance when i change the value.
I've also tried Form1 form1 = new Form1(); but the application crashes when i open settings form. Note that i've already have timer modifier set to public.
public partial class SettingsForm : Form
{
static Form1 formInstance;
...
if (Properties.Settings.Default.sync != Convert.ToInt32(textBox1.Text))
{
formInstance.timer1.Stop();
formInstance.timer1.Interval = 60000;
formInstance.timer1.Start();
}

It seems you have two classes:
A class Form1 that has a timer that you want to change,
A settings Form where you want to set the timer in Form1
In windows it is more common to let the form remember all changed settings, until the operator presses OK or Cancel, instead of updating the setting as soon as the operator changes the value.
Advantage: the operator can change the value several times, or even press a Cancel button. Only if the OK button is pressed the time value will be set.
Advantage: if the settings form controls several settings that relate to each other it is much easier to check for validity of the changed values when the operator expresses he is finishing changing the value when he presses OK
Disadvantage: the operator doesn't know the effect of the changed value until he presses OK.
This disadvantage can be solved by offering an Apply Now button.
Note that the OK / Cancel / Apply Now is standard Windows behaviour. Everyone will know what will happen, while a method that changes some settings of your form immediately and some not might be confusing.
Having said this, I assume the following:
Upon some event (probably clicking a button, or selecting a menu item) the form decides that it is time to show its settings Form.
The operator changes zero or more settings and presses OK or Cancel
If the operator pressed OK the main form is informed. It will ask the settings form for the settings and update his settings accordingly.
So let's make an example:
We have a Form1 with a button1 and a timer1, It has several settings, for instance TimerTimeout, Setting1 and Setting2.
If the operator clicks button1, then the settings form is shown.
Initially the settings form shows the current values of the timerTimeout, Setting1 and Setting2.
The operator can change the values of any of these settings.
When he finishes, he can click Cancel or Ok
The code is as follows:
public class SettingsForm : Form
{
public TimeSpan TimerTime {get; set;}
public int Setting1 {get; set;}
public string Setting2 {get; set;}
public void OnButtonOk_Clicked(object sender, ...)
{
if (!this.AllValuesOk())
{ // error in one of the values
// show message box
}
else
{
this.Close();
}
}
}
Now Let's show the settings form when button1 is clicked on Form1:
private void OnButton1_Clicked(object sender, ...)
{
using (var settingsForm = new SettingsForm)
{
settingsForm.TimerTime = this.TimerTime;
settingsForm.Setting1 = this.Setting1;
settingsForm.Setting2 = this.Setting2;
// now that the settings form is initialized
// we can show it and wait until the user closes the form
var dlgResult = settingsForm.ShowDialog(this);
// only use the new settings if the operator pressed OK:
if (dlgResult == DialogResult.OK)
{
this.TimerTime = settingsForm.TimerTime;
this.Setting1 = settingsForm.Setting1;
this.Setting2 = settingsForm.Setting2;
this.ProcessChangedSettings();
}
}
}
Note that the settings form doesn't have to know anything about Form1. This enables it to use the settings form for any form that has a TimerTimer, a Setting1 and a Setting2.
Do you also notice how easy it is to use the original settings if the user presses Cancel, or presses the cross in the upper right corner of the settings form or presses alt-F4, or whatever method he can use to cancel.
Also note that during changing, the operator can have incompabible settings, for instance a halve finished string, an incorrect timer time etc. Only the moment he presses OK the software checks if all values are filled in correctly.

pass form1 as parameter on the constructor of settingForm
private Form1 _objForm1;
public SettingForm (Form1 objForm1)
{
_objForm1 = objForm1;
}
Private ButtonClicked(sender,...)
{
_objForm1.timer1.Stop();
_objForm1.timer1.Interval = 60000;
_objForm1.timer1.Start();
}

Use properties in Form1 and access it from another form.. In Setting form create a private variable for example:
private int interval;
create a getter setter method:
public int Interval
{
get { return interval; }
set { interval = value; }
}
Then in SettingsForm return a this.DialogResult = DialogResult.OK; dialog result at the method end, for example at the end of the button click event.
In Form1 when you open the SettingsForm you can access the value set in SettingsForm:
if(settingsForm.ShowDialog() == DialogResults.OK)
{
timer1.Interval = settingsForm.Interval;
}

If you want to access the timer but not from an instance,
Form1.timer.Interval = 4;
you would have to go into "Form1.designer.cs" and find where it says
public Timer timer1;
and change it to
public static Timer timer1;

Related

How to make a button on a form be enabled from a different form?

Im making a game with a menu that opens new forms for each level. When you complete a level, it is supposed to congratulate you through a message box (it does) and then enable the next level's button on the different menu form. So I accessed the designer and made the buttons public and tried:
new LevelMenu().button2.Enabled = true;
But that didn't work.
I also tried doing:
public event Action levelCompleted;
//then down lower i did (after it is declared that you won the level):
if (levelCompleted != null)
levelCompleted();
W1L1.levelCompleted += () => LevelMenu.button2.Enabled = true;
But that give me the error of:
An object reference is required for the non-static field, method, or property 'The_Levels.W1L1.levelCompleted'
The form i'm working with is "W1L1", and "LevelMenu" is the menu form. Thanks in advance
You basically need a reference to your instance of LevelMenu.
So when you create your "W1L1" form, you might just pass the LevelMenu to it.
public class W1L1
{
private readonly LevelMenu _levelMenu;
public W1L1(LevelMenu levelMenu)
{
this._levelMenu = levelMenu;
}
//Where you want to enable the button
this._levelMenu.button2.Enabled = true;
}
It's not the best solution, in an architectural way, but it works.
But it would be better if you create a more OOP way for enabling the button of the next level.
When you open the next level open it as a separate object as a new form. Now when the level is completed you can access the public controls on that form from the originating class. Something like this might help:
LevelMenu NextLevel = new LevelMenu();
public event Action levelCompleted;
if (levelCompleted != null)
levelCompleted();
NextLevel.button2.Enabled = true;
here's what I did I hope this helps
I created 2 Forms
Form1 = where menu is (buttons), Form2 = the game level (i.e. level 1)
then in Form2 I added an even LevelCompleted that will notify form1 that the player completed the level
//add this to form2
//the delegate
public delegate void LevelCompleted(Int32 level);
//the event
public event LevelCompleted LevelCompletedEvent;
then on Form1 (the menu form) when you create an instance of Form2 (which has the event) subscribe to it and create a handler, in my case I added it after i created the instance of Form2
private void button1_CLick(object sender, EventArgs e)
{
Form2 level1 = new Form2();
level1.LevelCompletedEvent += new Form2.LevelCompleted(level1_LevelCompletedHandler);
level1.Show();
}
//and this is the handler method
void level1_LevelCompletedHandler(int level)
{
//the logic for controlling the button states
// the level parameter can be used to indicate what is the current level completed.
if(level == 1)
{
button1.Enabled = false;
button2.Enabled = true;
}
}
Note: that in Form2 (the game level) I created a field gameOver that can be used if he did not complete the game
If in case he is permitted to go to next level, You must raise the event in this form to notify Form1 (the menu)
that he (the user) completed the level and Form1 will execute the method level1_LevelCompletedHandler(int level).
I know this is not well explained but I hope I can give you an idea on the event.

Filling one form from another

I have two forms in my project, one is with button and second one is with two textboxes.
When I am clicking the first form button, I want to fill textbox in another.
code:
secondForm secondForm = new secondForm();
secondForm.MdiParent = this.MdiParent;
secondForm.fillForm("String");
if (formShown != true)
{
secondForm.Show();
formShown = true;
}
else
{
Application.OpenForms[secondForm.Name].Focus();
}
and
public void fillForm(string text)
{
if (String.IsNullOrEmpty(priceText1.Text))
{
priceText1.Text = text;
}
else
{
priceText2.Text = text;
}
}
looks simple, but when i am clicking button second time, its not detecting text in second form text box and entering data in textbox1 instead of textbox2, why?
The problem is that when you click the button a second time you're creating a second instance of the form, and then just not showing it (you're focusing the first instance instead). You should refactor the program so that you don't do that.
private secondform secondform = null;
private void Foo()
{
if(secondForm == null)
{
secondForm = new secondForm();
secondForm.MdiParent = this.MdiParent;
secondForm.Show();
}
secondForm.fillForm("String");
secondForm.Focus();
}
So a new instance is only created if we don't already have one, we fill the data every time, and then focus the form.
P.S. there's nothing wrong with focusing the form the first time, so I just left it after the end of the if. If there was something that should only happen when it's not the first time we could add an else to the if and put the code there.
P.S.S. secondForm isn't following standard naming conventions for the name of a class. Class names should start with an upper case letter, i.e. SecondForm. Among other issues, this removes the ambiguity about whether secondForm is refering to the type, or the instance of the type.
P.S.S.S. It may not be needed functionality in your case, but we may need to properly handle the case where the child form is closed and then the button is clicked again. The easiest way of handling this is to clear out the secondForm instance field when the form is closed (letting a new one be created when the button is next clicked, if that ever happens). Closures make this really easy, we just add this line right before secondForm.Show();:
secondform.FormClosed += (s, arg) => secondform = null;

Need to define control flow and functionalities

I have a project with requirements as below,
Login form opens up and asks for user name and password.
Login Successful - Login form closes and another main form opens and all the functionalities will be added here.
In the main form there is a Call button when clicked on it, it will pop a dial pad.
When the number is entered on the dial pad and clicked "ok", control comes back to the same main form.
When logout is clicked, It wil take me to the login screen again.
For this can anybody explain me the following points:
How do I tranfer the control from one form to another?
I have to make sure when user clicks on the close 'x' , I have to log out and close the windows?
Neeed some rough class information.
Thanks in advance.
This is what i used earlier to carry data from one form to other
public partial class DialPad : Form
{
public MainGUI guiObject;
public DialPad(MainGUI mG)
{
InitializeComponent();
guiObject = mG;
}
By the sounds of it your dialler form should be a dialog..
class MyDiallerDialog : Form
{
public String DialledNumber
{
get { return this.txtNumber.Text; } // Or however the form stores its number...
}
}
class MyMainForm : Form
{
void btnCall_Click(object sender, EventArgs e)
{
using (var dialog = new MyDiallerDialog())
{
if (dialog.ShowDialog() == DialogResult.OK)
{
String number = dialog.DialledNumber;
// do something interesting with the number...
}
}
}
}
For your point no. 2
I have to make sure when user clicks
on the close 'x' , I have to log out
and close the windows?
In the event FormClosing of the form, take a look at e.ClosingReason.
So if user closes using Close Button (X), then ClosingReason would be UserClosing. So check that and then write appropriate code therein.
How do I tranfer the control from one
form to another?
For e.g
If you want to get the number in main form from Dialpad form.
1st in the contructor of main form
public static MainForm instance = null;
public string numberInMainForm = null;
public MainForm()
{
instance = this;
}
now in your dialpad form, when user enters the number, you can pass the number (or any other variable.) to main form from the dialpad form directly.
In dialpad form just write:
MainForm.instance.numberInMainForm = number;
thats it. You are done !!
let us assume you 1st form is loginform,
Suppose User press OK on the login form, so on
OK_click()
event call another form.
suppose your name of the another form is MainForm.cs then you can call using...
MainForm mf = new Mainform()
Suppose you want to close the login form when user press OK of your logIn form you can keep the order in following way..
private void OK_Click(object sender, EventArgs e)
{
. . .
// your validations
//return bool (true or false ) to confirm you have complted validations
MainForm mf = new Mainform();
mf.show(); // or you can use mf.ShowDialog();
. . .
. . .
this.close();
}
When you will close the MainForm,its control will come directly to the next line after mf.show();
To close any form use
this.close() command.
I hope this will help you ands you can start working on your project now.
EDIT:
Add a new class file named commondata.cs and in that use static variables like
public static string myString = "";
You can keep all the static functions and variables in the common file like commonData.cs so that you can modify its value from anywhere and can be used from anywhere.
Before closing your current form store the information in the static myString so even if u close the current form related information will be stored in myString & you can access it in any form using commonData.myString command.
string temp = commonData.myString;
Regards,
Sangram Nandkhile.

Changing the property of a control on another form

Basically, I have a settings window, and when you click "OK", it's suppose to apply settings to the main form (eg, set font of a control, etc), and then close.
frmmain frm = new frmmain();
frm.OLVAltBackColor = Color.Aquamarine ;
I tried that, but it only applies the settings to that instance, and you can see it if you do frm.Show();
I'm trying to make it so the already opened form has it's control's properties changed.
What you are trying to do is not working because you are creating a NEW instance of your main form and updating that rather than the first instance. It is possible to update the main form by keeping a reference to it in your settings form... but...
...it sounds like you are approaching this from the wrong direction.
Don't make the settings form dependent on the main form. Instead create the settings form from the main dialog.
class SettingsForm : Form
{
// You need to ensure that this color is updated before the form exits
// either make it return the value straight from a control or set it
// as the control is updated
public Color OLVAltBackColor
{
get;
private set;
}
}
In your main form
(I'm assuming some kind of button or menu click)
private void ShowSettingsClicked(object sender, EventArgs args)
{
using (SettingsForm settings = new SettingsForm())
{
// Using 'this' in the ShowDialog parents the settings dialog to the main form
if (settings.ShowDialog(this) == DialogResult.OK)
{
// update settings in the main form
this.OLVAltBackColor = settings.OLVAltBackColor;
}
}
}
Apply the property change to the form that already exists and is already shown instead of creating a new form and changing that one.
In this code you're creating a new instance of the frmmain. Any changes you make to that new object will happen in the new object, not the one you actually want to change.:
frmmain frm = new frmmain(); //Creating a new object isn't the way.
frm.OLVAltBackColor = Color.Aquamarine ;
What you're looking for is a way to call on the already existant frmmain class and change the property of that.
Edit, for example:
using System;
class Statmethod
{
//A class method declared
static void show()
{
int x = 100;
int y = 200;
Console.WriteLine(x);
Console.WriteLine(y);
}
public static void Main()
{
// Class method called without creating an object of the class
Statmethod.show();
}
}

Where can I find a good tutorial on bubbling?

I'm new to C# and would like to allow to Windows forms to comminicate with each other. I googled bubbling in C# but it wasn't much help. What are some good ways I can learn bubbling?
EDIT: I want to have an options form that is shown/created when my user clicks on Edit->Preferances. I then want the settings the user changed in the options form to be relayed to the main form.
Two approaches:
Put properties on your preferences form and access them from the main form when the user clicks OK.
if (preferenceForm.ShowDialog() == DialogResult.OK)
{
this.Color = preferenceForm.UserSelectedColor;
//etc...
}
Send your preference form a delegate from the main form and let the preference form call it with the appropriate changes.
class FormSettings
{
object Color {get, set}
}
class MainForm
{
...
void ChangeSettings(FormSettings newSettings)
{ ... }
void EditPreferences_Click(...)
{
...
EditPreferencesForm editPreferences = new EditPreferencesForm(this.ChangeSettings)
editPreferences.ShowDialog();
}
}
class EditPreferencesForm
{
...
ChangeSettingsDelegate changeSettings;
FormSettings formSettings;
void OkButton_Click(...)
{
changeSettings(formSettings);
}
}
You don't state as much, but is the main form also the form that contains the Edit->Preferences menu? If so, you are already at the correct point in the code
// This is the event handler in the main form
private void mnuEditPreferencesClicked...
{
FrmPreferences frmPreferences = new FrmPreferences();
frmPreferences.ShowDialog(this);
// Preferences saved, implement changes to main form here
}
If the preferences form is not generated from the main form, fire off an event when the preferences form closes, and have the main form handle the event that way.

Categories