C# accessing control propertes from static void - c#

I have form with button and checkbox. if i hit button static void is called which call non static void which shows messagebox with the checkbox.checked.toString()
The problem is if i change the checkbox value it always shows false
Code is
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
public void y()
{
MessageBox.Show(checkBox1.Checked.ToString());
}
static void x()
{
Form1 f = new Form1();
f.y();
}
private void button1_Click(object sender, EventArgs e)
{
x();
}
}
}

Method x instantiates a new form. The check box on the new form will also be new (created with the form) and will have a default value of false.
What exactly are you trying to do? Why create a new form when the button is pressed? If you really want to do this then you need to set the new form's check box state after you call Form f = new Form1();

I guess you have probably came from a Visual Basic background like I do.
In C#, form are just instances of a Form class, they does not have special status like in the days of VB6.
When you call new Form1() you are basically creating a new form not accessing the same form. As anyone form can have multiple instances because it really is just a C# class underneath.
You can fix this by having the x() method takes the current form as a parameter
static void x(Form1 theForm)
{
theForm.y();
}
private void button1_Click(object sender, EventArgs e)
{
x(this);
}
The this parameter inside a form class points to the form instance itself.
You should now gets the correct value instead of the default value when the form is being created.
I suppose you have a need for x() to be static, no? But if that isn't the case, removing static from x() might be a better solution.
void x()
{
this.y();
// or you can just omit the this qualifier and call just y();
}

Try
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
public void y()
{
MessageBox.Show(checkBox1.Checked.ToString());
}
static void x(Form f)
{
f.y();
}
private void button1_Click(object sender, EventArgs e)
{
x(this);
}
}

It's because your instantiating a new Form1 inside x(), try passing 'this' to the x method as a parameter.

You're creating a new Form1 instance. Why are you doing that? When you create a new form, a new checkbox is created as well. The checkbox on the form looks like is set to false (not checked) by default, therefore, every time you create a new instance of the form, it comes up as false.

The checkbox1 in y() is on a completely different Form1 - the one you created in x. Simply get rid of x() and it should work:
private void button1_Click(object sender, EventArgs e)
{
y(); // not x();
}

your issues are in the x() method, what you're doing there is actually making an entirely new form and checking that forms check box, which would obviously be instantiating as false.
Rather then calling x() you should call y().
Or, alternatively, put the messagebox.show in the buttonclick method itself.

If you need to access some form instance from static method, you need to save somewhere a reference to that form.
class Program
{
public static Form thatForm;
public static void Main(string[] args)
{
MyForm form = new MyForm();
thatForm = form;
Application.Run(form);
}
}
class MyForm : Form
{
void Foo()
{
Program.thatForm.somethingPublic();
}
}

Related

C# Call a method from a different form class?

Ok, so I have a method in one class and I'm trying to call it from another class.
Form1:
public void ChangeBack(Color clr)
{
this.BackColor = clr;
}
Form2:
public void ChangBackColor_Click(object sender, EventArgs e)
{
if (ColorDialog.ShowDialog() == DialogResult.OK)
{
Form1.ChangeBack(ColorDialog.Color);
}
}
But I need to make the ChangeBack method static to be able to call it. So:
Form1:
public static void ChangeBack(Color clr)
{
this.BackColor = clr;
}
But then I can't use "this." as the void doesn't allow it because it's static. And I can't create a new form1 because it needs to run overall in two windows.
Please help!C
When you are working with multiple forms, you need to pass a reference to the second form, so that it "knows" about the first form. To do this you will need to change the constructor of your second form, and add a private reference to that form, like so:
class Form2 : Form
{
//Variables
private Form1 _ParentForm; //Add this here
//Constructor
public Form2(Form1 parentForm)
{
InitalizeComponent();
_ParentForm = parentForm; //Add this here
}
}
The, when you create the second form on your main form, you can use this to pass the reference of itself on to the new form:
class Form1 : Form
{
public void ChangeBack(Color clr) //No longer needs to be static
{
this.BackColor = clr;
}
public void CreateSecondForm()
{
Form2 secondForm = new Form2(this);
secondForm.Show();
}
}
Then you can call any function on the parent form (i.e. Form1) from the second form like so:
public void ChangBackColor_Click(object sender, EventArgs e)
{
if (ColorDialog.ShowDialog() == DialogResult.OK)
{
//Access Form1's reference with _ParentForm instead of Form1
_ParentForm.ChangeBack(ColorDialog.Color);
}
}
If you work with 2 different WinForm windows you should simply pass a reference from one window to the other (typically using constructor). For instance:
var childForm = new ChildForm(this); // where this is your main WinForm
after that you can use the reference to the main WinForm to call it's methods.
That's correct, you cannot make the method static and access instance of the object.
Change BackColor to a static property or change your method to a non static one

Update textbox from a different class

I'm relatively new to C# and come a bit stuck.
I've got a Rich Textbox on a form, and I would like to update this from a different class to the Form itself.
I first tried
Form1.outputTextbox.AppendText(string);
but the text box was not accessible, made sense. So instead I tried to make a function. On Form1 I created the function
public void updateTextBox(string new_text)
{
outputTextBox.AppendText(new_text);
}
and in the class I used.
Form1.updateTextBox("apple");
The problem I'm having is the only way my class can see the function is if I make it the function static, but when I do that get an error "An object reference is required for the nonstatic field, method, or property 'member'"
Am I close or going to wrong way about this completely? Any help would be appricated.
Alternatively, you can do something like the following. This takes advantage of custom arguments and events.
namespace WindowsFormsApplication3
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
public partial class Form1 : Form
{
TextBox textBox;
SomeClass someClass;
public Form1()
{
InitializeComponent();
Initialize();
BindComponents();
}
private void BindComponents()
{
//EventHandlers
this.Load += new EventHandler(Form1_Load);
this.someClass.TextUpdatedEvent += new EventHandler(someClass_TextUpdatedEvent);
}
void someClass_TextUpdatedEvent(object sender, EventArgs e)
{
this.textBox.Text = (e as FormArgs).Text;
}
private void Initialize()
{
this.textBox = new TextBox();
this.someClass = new SomeClass();
}
void Form1_Load(object sender, EventArgs e)
{
this.Controls.Add(textBox);
}
}
public class SomeClass
{
public event EventHandler TextUpdatedEvent = delegate { };
public void UpdateText(string text)
{
if (TextUpdatedEvent != null)
{
TextUpdatedEvent(this, new FormArgs() { Text = text });
}
}
}
public class FormArgs : EventArgs
{
public string Text { get; set; }
}
}
If you do it this way, you can update the form text like this:
someClass.UpdateText("changing the text on the form");
You are trying to access the function from the class instead of the object.
Use
Form1 myForm = new Form1();
...
myForm.updateTextBox("whatever");
Also be aware of thread issues here. What triggers the outside code? Is it another ui action, then all is well. Does it come from another thread, then you´ll have to handle this.
Pass Form1 instance to the other class via constructor or property. Then you can access outputTextbox from the other class.
public class OtherClass
{
private Form1 form1;
public OtherClass(Form1 form1)
{
this.form1 = form1;
}
private void ChangeText()
{
form1.outputTextBox.AppendText("hello world");
}
}
Instantiate OtherClass from Form1.cs and pass its instance.
In Form1.cs:
OtherClass obj = new OtherClass(this);
I know it is very late, but maybe someone need the solution...
you can access to all controller from another form without create object by pass it as parameter to constructor...
for Example
public partial class Form2 : Form
{
MainForm mainForm;
public Form2(MainForm mainForm)
{
InitializeComponent();
this.mainForm = mainForm;
txtRecive00.TextChanged += new EventHandler(txtRecive8changed);
}
void txtRecive8changed(object sender, EventArgs e)
{
mainForm.txtRecive1.Text += txtRecive00.Text;
}
in my case I can update the text in mainForm.txtRecive1.Text from Form2...
and in MineForm we creat object from Form2 like that:
Form2 f2 = new FormMeasure(this);
for more Info show this short video https://www.youtube.com/watch?v=CdH8z_JNi_U

How do pass parameters from 1 form to another?

My program has a main form where I keep a repository of values from other sub forms. For some reason the sub form is giving me an error:
an object reference is required for the non-static field
This is my main form:
public partial class frm_SystemLog : Form
{
public frm_SystemLog()
{
InitializeComponent();
}
public string TextBoxValue
{
// suppose to get value from other forms
get { return this.textBox1.Text; }
set { textBox1.Text = value; }
}
private void frm_SystemLog_Load(object sender, EventArgs e)
{
Log frm_LoginMenu = new Log();
frm_LoginMenu.ShowDialog();
}
}
This is my sub form:
public partial class Log : Form
{
public Log()
{
InitializeComponent();
}
private void button2_Click(object sender, EventArgs e)
{
// this is where the error happens
frm_SystemLog.TextBoxValue = "SomeValue";
this.Close();
}
}
you should create a property in your log form then set its value when you are accessing it
//in log form
public String MyValue{get;set;}
then in properties of your button2 of log form choose dialogresult and set it to ok
then in your button2 click event
private void button2_Click(object sender, EventArgs e)
{
MyValue = "SomeValue";
//no need to close ,dialogresult will do it...
}
then in your frm_SystemLog form do this
private void frm_SystemLog_Load(object sender, EventArgs e)
{
Log frm_LoginMenu = new Log();
frm_LoginMenu.ShowDialog();
if(frm_LoginMenu.ShowDialog() == DialogResult.OK)
{
this.TextBoxValue = frm_LoginMenu.MyValue;
}
}
this should solve your problem.
frm_SystemLog.TextBoxValue isn't accessible from button2_Click, because it's in a different class.
Currently you're trying to reference an object on your parent form class, not an instance of your class. In that case, the only objects you can reference are static ones, hence the error you're getting.
You need an actual reference to the instance of your parent form. Change your Log class as follows:
public partial class Log : Form
{
private frm_SystemLog parentForm;
public Log(frm_SystemLog parentForm)
{
InitializeComponent();
this.parentForm = parentForm;
}
...
...
Then instantiate your sub form using:
Log frm_LoginMenu = new Log(this);
Read "Understanding Classes, Methods, and Properties in C#" for more information, in particular:
There are two kinds of methods in C#. They are:
Instance Method
Static Method
Instance Methods are methods declared outside the main method and can be accessed only by creating an object of the corresponding class.
Class methods also are declared outside the main method but can be accessed without creating an object of the class. They should be declared with the keyword static and can be accessed using the classname.methodname syntax.

Call public parent function from child class

Inside my Main method I'm instantiating the UpdateDialog class inside which based on if the user presses a button or not I need to call function1() from Main. Here is the code:
public partial class Main : Form
{
public void function1()
{
doing_stuff_here();
}
private void button1_Click(Object sender, EventArgs e)
{
var update = new UpdateDialog();
update.ShowDialog();
}
}
public partial class UpdateDialog : Form
{
private void button2_Click(object sender, EventArgs e)
{
//call here function1() from Main
}
}
What should I do to be able to call function1() from Main inside the partial class UpdateDialog?
LE: although the method suggested by Styxxy seems right it doesn't work well in my app because of cross-thread invalid operation so I ended up using the delegate workaround suggested by Cuong Le.
You'll have to have an instance of the Main form in your UpdateDialog form. As you say that UpdateDialog is a child form of your Main form, I guess that you create the UpdateDialog in your Main form and do a show there. Before showing that form, you could assign the Parent property.
var updateDialog = new UpdateDialog();
// Or use "UpdateDialog updateDialog = new UpdateDialog();" as people like Andreas Johansson don't like the "var" keyword
// Do other stuff here as well
updateDialog.Parent = this;
// Or use Show() for non modal window
updateDialog.ShowDialog();
You get the error ArgumentException: Top-level control cannot be added to a control.. Now this can be solved in two ways.
You can set the TopLevel property to false on your Main form (I'm not a huge fan of this).
You can use the Owner property to your Main form (this). Below two ways of doing it.
You can set the Owner manually:
updateDialog.Owner = this;
Or you can add this as parameter to the Show(owner) or ShowDialog(owner) methods; this way, the Owner is also being set.
updateDialog.Show(this);
// or
updateDialog.ShowDialog(this);
"Full" code makes this:
var updateDialog = new UpdateDialog();
// Do other stuff here as well
updateDialog.Owner= this;
updateDialog.ShowDialog(); // or use .Show()
// or
updateDialog.ShowDialog(this); // or use .Show(this)
I suggest you create an event in UpdateDialog then subscribe it after you create an instance inside the Main class. This way you have a better separation between these 2 classes.
public partial class Main
{
public void function1()
{
doing_stuff_here();
}
private void button1_Click(object sender, EventArgs e)
{
var update = new UpdateDialog();
update.OnButton2Click += OnUpdateDialogButton2Click;
update.ShowDialog();
}
void OnUpdateDialogButton2Click(object sender, EventArgs e)
{
function1();
}
}
public partial class UpdateDialog
{
public event EventHandler<EventArgs> OnButton2Click;
private void button2_Click(object sender, EventArgs e)
{
//call here function1() from Main
if (OnButton2Click != null)
{
this.OnButton2Click(this, e);
}
}
}
Pass Main class instance to your Update Form and store it in instance variable -
Main mainWindow = null;
public UpdateDialog(Main mainForm)
{
mainWindow = mainForm;
}
private void button2_Click(object sender, EventArgs e)
{
mainWindow.function1();
}
And from Main method -
private void button1_Click(Object sender, EventArgs e)
{
var update = new UpdateDialog(this);
update.ShowDialog();
}
You could turn it around, and let Main form listen to clicks from the UpdateDialog.
In Main:
private void button1_Click(Object sender, EventArgs e)
{
var update = new UpdateDialog();
update.OnSomethingClicked += function1;
update.ShowDialog();
}
void form_OnSomethingHappened(object sender, EventArgs e)
{
// Do the stuff you want
}
In UpdateDialog:
public event EventHandler OnSomethingHappened;
private void button2_Click(object sender, EventArgs e)
{
EventHandler handler = OnSomethingHappened;
if (handler != null) handler(this, e);
}
The ShowDialog() method returns a DialogResult you can call function1 one of after the dialog is closed.
http://msdn.microsoft.com/en-us/library/c7ykbedk.aspx
Can pass the Main class like a reference.
For example:
public partial class Main : Form
{
//make it internal, if UpdateDialog in the same assembly, and it only one that would use it. In other words hide it for outside world.
internal void function1()
{
doing_stuff_here();
}
....
}
public partial class UpdateDialog : Form
{
private MainForm _main = null;
public UpdateDialog (MainForm main) { //Accept only MainForm type, _not_ just a Form
_main = main;
}
private void button2_Click(object sender, EventArgs e)
{
_main.function1(); //CALL
}
}
Something like this. You can change this accroding to your precise requirements, but this is a general idea.
Approach #1
You need to create an instance of class Main.
Main foo = new Main();
foo.function1();
Approach #2
You need to declare the method as static.
public static function1(){ ... }
....
Main.function1();
You can make your function1 a Partial method and this way you can use it in all your partial classes.
Partial methods allow the definition of a method to be located in one file and the body of the method to be optionally defined in another file. They can only be used in partial classes and were introduced as language features in C# 3.0 and Visual Basic 9.0, the versions that shipped with the .NET Framework 3.5 and Visual Studio 2008.
So what you can do is modify like this
public partial class Main : Form
{
public partial void function1()
{
doing_stuff_here();
}
private void button1_Click(object sender, EventArgs e)
{
var update = new UpdateDialog();
update.ShowDialog();
}
}
public partial class UpdateDialog : Form
{
public partial void function1();
private void button2_Click(object sender, EventArgs e)
{
function1();
}
}

How to reference a form from subform?

Well here is the thing, I have MainForm that call OrderForm.Show().
Now I want to call public function in MainForm with a button, but I cant.
Here is the code in MainForm:
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
}
// Main form
private void MainFrm_Load(object sender, EventArgs e)
{
FormOrder frmO = new FormOrder();
frmO.Show();
}
public void Refresh()
{
// some action
}
}
And in OrderForm I do this:
public partial class FormOrder : Form
{
public FormOrder()
{
InitializeComponent();
}
private void ShowForm()
{
// some action
}
private void btnCopy_Click(object sender, EventArgs e)
{
Form form = Form.ActiveForm as frmMain;
if (form != null)
{
form.Refresh();
}
}
}
so in the Program I run MainForm.Show() then load OrderForm. Then I when I click Copy button, it will run Public Function Refresh in MainForm. But I cant make it work, it always return null in:
Form form = Form.ActiveForm as frmMain;
so how can I actually get the active form, is it another solution? or I get it wrong??
Thanks in advance for the answer :)
You're getting a null because your active form is the one you're in and it is not of type frmMain. (I think you may actually be confusing an active form for a parent form?)
There are so may ways to do this. You could make your frmMain a singleton but that's weird and ugly and not recommended of late or you could pass a reference of it to its children somehow. Here's one, simple way:
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
}
// Main form
private void MainFrm_Load(object sender, EventArgs e)
{
FormOrder frmO = new FormOrder(this); // pass a ref of self
frmO.Show();
}
public void Refresh()
{
// some action
}
}
And in OrderForm:
public partial class FormOrder : Form
{
private frmMain _parent; // create a field that refers to the parent
public FormOrder(frmMain parent) // mod the constructor
{
if (parent == null) throw new NullReferenceException("Can't be NULL!!!"); // check clause
_parent = parent; // assign the ref of the parent
InitializeComponent();
}
private void ShowForm()
{
// some action
}
private void btnCopy_Click(object sender, EventArgs e)
{
_parent.Refresh(); // make the call to parent
}
}
You could make this better by using an interface but the general idea would be the same.
I would not suggest you take the route to access the active form to accomplish your target. What you need to do is to pass a reference of the MainForm to the OrderForm, so OrderForm could use the reference to call any method on the MainForm.
private void MainFrm_Load(object sender, EventArgs e)
{
FormOrder frmO = new FormOrder();
frmO.MainForm = this;
frmO.Show();
}
And in FormOrder class you should add a new attribute MainForm, and use the attribute to reference the calling form :-
public partial class FormOrder : Form
{
public Form MainForm;
public FormOrder()
{
InitializeComponent();
}
private void ShowForm()
{
// some action
}
private void btnCopy_Click(object sender, EventArgs e)
{
if (MainForm != null)
{
MainForm.Refresh();
}
}
}
You need to have a reference to the mainForm and/or mainForm's button click event that lives outside of mainForm. You can do this is in various ways. Create a static class that has a reference to mainForm, create a static class that has a delegate to the mainForm click event, pass mainForm into the contructor for childForm, pass in a delegate to mainForms click event to the the constructor for the childForm. Create a static method that handles the click event then use that from within childForm.
It really all depends upon what you want to to do, what you need to do, and how you desire to do it.
While the other answers are absolutely correct, I'd like to suggest a much easier yet "dirty" way to do it.
Every component has a Tag property where you can store any user-defined value or reference in. The idea is to save a reference to the main form in the second form's Tag, and access it from the button click event handler.
The good thing is that you do not have to write a lot of code, or create any data structure.
The dirty thing about it is that neither the framework at runtime nor the compiler at compile-time have any idea what you store in .Tag, and since it is not typed correctly, you are doing a type cast, depending on you storing the correct value there beforehand.
If you store the wrong value there, you might have a hard time debugging the cause since the symptom does not signal where you put the wrong value into Tag. So wild Tag usuage in a team of programmers is a good thing if you want to give birth to many unexpected hard-to-detect-and-fix bugs :)
Also, there is only one Tag per component. If you need more than one user-defined value, you might end up creating a custom data structure which Tag then holds a reference to, but that probably is a bigger mess than all of the other suggestions.
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
}
// Main form
private void MainFrm_Load(object sender, EventArgs e)
{
FormOrder frmO = new FormOrder();
frmO.Tag=this;
frmO.Show();
}
public void Refresh()
{
// some action
}
}
public partial class FormOrder : Form
{
public FormOrder()
{
InitializeComponent();
}
private void ShowForm()
{
// some action
}
private void btnCopy_Click(object sender, EventArgs e)
{
Form form = Tag as frmMain; // form now references the main form
if (form != null)
{
form.Refresh();
}
}
}
A good example for a quick and dirty solution, with limitations so inherent that you usually identify them only when it is too late -- that's why I am telling in the first place ;)

Categories