This question already has answers here:
Call method on another form that is still open?
(2 answers)
Closed 9 years ago.
I create a form that contains a public field and a button. The button creates another form and shows it as dialog. Can I access to the public fields on main form? the main form run in main method like this:
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
public partial class MainForm : Form
{
public int number;
public MainForm()
{
InitializeComponent();
}
private void button_Click(object sender, EventArgs e)
{
(new SecondForm()).ShowDialog();
}
}
public partial class SecondForm : Form
{
public SecondForm()
{
InitializeComponent();
}
void Method()
{
//How can I access to number?
}
}
I don't want use constructor because there are a lot of variables in mainform.
You can use the ShowDialog Method that sets the owner of the created form.
secondForm.ShowDialog(this);
usage in your second form:
var temp = ((MainForm)this.Owner).number;
Create an object of the MainForm class and you can use it access all the public variables in the class
MainForm f = new MainForm();
int a = f.number;
This might not really work as it will create a new instance of the MainForm class and you might not get the desired result, so a better will be to make number static.
public static int number;
Then you can use
int a = MainForm.number;
Sure, just do:
var form = new SecondForm();
form.<property> = <value>
// ...
DialogResult result = form.ShowDialog();
if (result == DialogResult.OK)
{
// ...
You said you don't want to use the SecondForm constructor to pass all of those variables from MainForm. Why not just create a class to hold the values and pass the class instance between the two?
public class FormData
{
public int number;
public int anotherInt;
public FormData(int num)
{
number = num;
}
}
public class SecondForm : Form
{
private FormData myData;
public SecondForm(FormData data)
{
myData = data;
}
}
public void AMethodInMainForm()
{
FormData d = new FormData(this.number);
d.anotherInt = 26;
SecondForm frm = new SecondForm(d);
}
Declare your number as public static int number and then:
public partial class SecondForm : Form
{
public SecondForm()
{
InitializeComponent();
}
void Method()
{
MainForm.number = // something
}
}
Define a public number in SecondForm
public int number;
Then before you show SecondForm try this:
SecondForm f2 = new SecondForm();
f2.number = this.number;
f2.ShowDialog();
Then you can access your number inside of your SecondForm.This works if you call number variable several times from your methods inside of your form2.But if you want access number in Form1 whenever you want,you should define it as Static and Public
Related
I try to get working a debugger window which tell me what is going on in my code while running.
So I have one mainform which write in debug console when it runs. and a second form which write in my debug console too.
Now I found another way to do it but I'm wondering what it really do.
Source(my code but their Idea):: this site QA: Can I make a Form a singleton?
DebugConsole create a static Instance::
public partial class DEBUGConsole : Form
{
public static DEBUGConsole Instance;
public DEBUGConsole()
{
Instance = this;
InitializeComponent();
}
internal void SetValueFunction(string value)
{
ListBoxDEBUG.Items.Add(value);
}
}
Form1 create the Instance to share::
public partial class MainForm : Form
{
public DEBUGConsole ConsoleDEB;
internal SecondForm Formsnd2;
public MainForm()
{
InitializeComponent();
DEBUGConsole ConsoleDEB = new DEBUGConsole();
ConsoleDEB.Show();
DEBUGConsole.Instance.SetValueFunction("Hello 1");
Formsnd2 = new SecondForm();
Formsnd2.Show();
}
private void textBoxForm1_TextChanged(object sender, EventArgs e)
{
DEBUGConsole.Instance.SetValueFunction("line has changed 1 : " +textBoxForm1.Text);
}
}
and Form2 use it too::
public partial class SecondForm : Form
{
public SecondForm(/*DEBUGConsole _ConsoleDEB*/)
{
InitializeComponent();
DEBUGConsole.Instance.SetValueFunction("Hello 2");
}
private void textBoxForm2_TextChanged(object sender, EventArgs e)
{
DEBUGConsole.Instance.SetValueFunction("line has changed 2 : " + textBoxForm2.Text);
}
}
Is that correct?
Is there only one Instance of DEBUGConsole in here?
Should it be sealed?
Is that a way to Singleton?
Thanks
So I roughly got this:
public partial class Form1 : Form
{
GameEngine engine;
public Form1()
{
engine = new GameEngine();
}
public void repaint()
{
}
}
class GameEngine
{
public void update()
{
}
}
Now i wanna add something to the update() method, which makes it call the repaint() method, inside of that instance of the Form1 class, in which the respective object of the GameEngine class was created.
In java i could've done it like this
engine = new GameEngine()
{
public void repaintCaller()
{
repaint();
}
};
and call repaintCaller() in the update() method, but that doesn't work in c#, now what is the equilvalent way to do this in c#?
One way to have it is:
public partial class Form1 : Form
{
GameEngine engine;
public Form1()
{
engine = new GameEngine();
engine.update(this);
}
public void repaint()
{
}
}
class GameEngine
{
public void update(Form1 form)
{
form.repaint();
}
}
You could pass to the GameEngine.update method an Action delegate to the repaint method in the form instance
public partial class Form1 : Form
{
GameEngine engine;
public Form1()
{
engine = new GameEngine();
// I put the call here for demo purpose,
// of course you call the engine.update
// method when you need and where you want
engine.update(repaint)
}
public void repaint()
{
Console.WriteLine("repaint called in the Form1 instance");
}
}
class GameEngine
{
public void update(Action clientUpdate)
{
if(clientUpdate != null)
clientUpdate.Invoke();
// or just... clientUpdate();
}
}
The parameterless Action delegate in C# is a way to pass, as parameter, a method (repaint) to the called method (update). Of course, you could pass the whole Form1 instance to the update but this approach binds the GameEngine class to the Form1 class. With the Action approach you are free from this coupling and you could pass any other method that returns void and doesn't take any parameter defined in any class of your program. This frees your GameEngine.update method from any specific bind to the caller.
I would try something like that
class GameEngine
{
public void update(ref Form1 caller)
{
caller.Refresh() //msdn says "Forces the control to invalidate its client area and immediately redraw itself and any child controls."
}
}
public partial class Form1 : Form
{
[...]
engine = new GameEngine()
engine.update(ref This)
}
I'm not sure of anything, i'm not used to C#.
I just hope it will help a bit :)
You can also set Events from your form, like this:
public partial class Form1 : Form
{
GameEngine engine;
public Form1()
{
InitializeComponent();
engine = new GameEngine();
engine.repaintRequired += engine_repaintRequired;
engine.update();
}
private void engine_repaintRequired(object sender, EventArgs e)
{
repaint();
}
public void repaint()
{
Console.Write("repaint");
}
}
class GameEngine
{
public event EventHandler repaintRequired;
public void update()
{
onRepaintRequired();
}
private void onRepaintRequired()
{
if (repaintRequired != null)
repaintRequired(this, new EventArgs());
}
}
My main Form1.cs as below
public partial class Form1: Form
{
Test _Test = new Test()
public Form1()
{
InitializeComponent();
_Test._TestMethod();
}
public void _MainPublicMethod(string _Message, string _Text)
{
MessageBox.Show(_Message);
TextBox1.Text = Text;
}
}
My Test.cs as below
class Test
{
Form1 _Form1 = new Form1();
public void _TestMethod()
{
_Form1._MainPublicMethod("Test Message", "Test Text");
}
}
When i debug my project, codes doesn't work.
Thank you in advance.
You can modify this code, add parenthesis ()
Form1 _Form1 = new Form1();
I guess you want to call the mainpublicmethod on the owner form, not a new instance of the owner form.
like this:
public partial class Form1: Form
{
Test _Test = new Test()
public GrabGames()
{
InitializeComponent();
_Test._TestMethod(this); //pass this form to the other form
}
public void _MainPublicMethod(string _Message, string _Text)
{
MessageBox.Show(Message);
TextBox1.Text = Text;
}
}
class Test
{
public void _TestMethod(Form1 owner)
{
//call the main public method on the calling/owner form
owner._MainPublicMethod("Test Message", "Test Text");
}
}
Your code shows a common misunderstanding (or a lack of understanding of a basic OOP principle).
When, inside form1, your code calls _Test._TestMethod() you are calling a method that 'belongs' to the instance of class Test defined and initialized in your form1. In turn, that instance try to call the method _MainPublicMethod defined in the class Form1. But, because to call that method (an instance method, not a static method) you need an instance of Form1, you declare and initialize ANOTHER instance of Form1
You end up with two instances of the class Form1 opened and the call is resolved by the second instance of Form1 not from the instance that had called _TestMethod initially.
To avoid this problem you need to pass the reference to the instance of Form1 that calls Test_Method and use that instance inside Test to call back on the public method.
So, when calling Test_Method pass the current instance of Form1
public Form1()
{
InitializeComponent();
_Test._TestMethod(this);
}
and in Test.cs
class Test
{
Form1 _frm = null;
public void _TestMethod(Form1 f)
{
_frm = f;
_frm._MainPublicMethod("Test Message", "Test Text");
}
}
Hello everyone I am trying to make since of what I am doing wrong or maybe I am over thinking it again. I am trying to create a class and in the class I am calling 2 private variables such as num1 and num2. Then i create a public property that corresponds to num 1 and num2. Then after I create that I need to create a public overriable method called calculate and this will add the two variables together and returns the results. Then I have a add button that I have to add the code to the button that adds the two numbers and output the result to a messagebox.I have tried a couple different ways and I still am not getting it.
Here is code 1:
public abstract class CalulateValues
{
protected List<int> values = new List<int>();
public void AddValue(int value) { values.Add(value); }
public abstract int Calculate();
}
public class Add : CalulateValues
{
public override int Calculate()
{
return values.Sum(x => x);
}
}
and here is code 2 I tried:
class CalculateValues
{
private int _num1;
private int _num2;
public int Num1
{
get
{
return _num1;
}
set
{
_num1 = value;
}
}
public int Num2
{
get
{
return _num2;
}
set
{
_num2 = value;
}
}
public virtual int calculate()
{
return _num1 + _num2;
}
}
Now when it comes with the button I have tried this code:
public partial class Form2 : Form
{
public Form2()
{
CalculateValues myAdd = new CalculateValues();
MulitplyValues Add = new MulitplyValues();
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int total = myAdd.Add(int.Parse(textBox1.Text), int.Parse(textBox2.Text));
MessageBox.Show(total.ToString());
}
I am not too sure what I am doing wrong maybe I am not laying out the code the right way.
You have declared myAdd as a local variable in the Form2 constructor. Declare it as a global variable in order to be able to call it from button1_Click()
In addition to this, are you getting any error or exception? Second, where did you declare Add method that accepts two parameters?
public partial class Form2 : Form
{
CalculateValues myAdd;
public Form2()
{
InitializeComponent();
myAdd = new CalculateValues();
}
private void button1_Click(object sender, EventArgs e)
{
int total = myAdd.Add(int.Parse(textBox1.Text), int.Parse(textBox2.Text));
MessageBox.Show(total.ToString());
}
}
And then go and look up firstly a C# tutorial, then look at detail on variable scope.
int total = myAdd.Add(int.Parse(textBox1.Text), int.Parse(textBox2.Text));
myAdd has no Add method at all. It is AddValue. And you should call Calculate and retrieve the result.
Declare myAdd as member variable instead local in constructor.
And try that:
myAdd.AddValue(int.Parse(textBox1.Text)
myAdd.AddValue(int.Parse(textBox2.Text);
int total = myAdd.Calculate();
MessageBox.Show(total.ToString());
Multiple bugs in your code.
You don't have a method Add, you shoudl use the method calculate like this
private void button1_Click(object sender, EventArgs e)
{
int total = myAdd.Add(int.Parse(textBox1.Text), int.Parse(textBox2.Text));
MessageBox.Show(total.ToString());
}
You need to declare the myAdd variable outside of the constructor, even if you only initialize in the Form2() constructor.
Your CalculateValues class does not have an "Add" method.
Instead you should be calling the "Calculate" method like this:
public partial class Form2 : Form
{
public Form2()
{
CalculateValues myAdd = new CalculateValues();
MulitplyValues Add = new MulitplyValues();
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int total = myAdd.Calculate(int.Parse(textBox1.Text), int.Parse(textBox2.Text));
MessageBox.Show(total.ToString());
}
I have a simple forms program that I have been fighting with for a while now. I simply want to be able to call a method from a different class file (when a certain step is triggered in the code in that class file) in order to insert a string in the listBox.
Here is my main method, pretty standard:
class Program
{
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
}
Here is the function which resides in my MainForm.cs file, which I can call just fine from that class file (via 'TextToBox(myString);'):
public partial class MainForm : Form
{
...
// Function to output results to main Listbox window
public void TextToBox(string aString)
{
// Place messages in Main Display list box window
this.listBox1.Items.Insert(0, aString);
}
...
}
But my problem is when I am in another class and I want to call 'TextToBox(myString);'. If I create another object reference of the MainForm, the code compiles fine but nothing will show up in the listBox. How do I do this? I cannot simply make TextToBox() static. I know I must create the object reference but I can't figure out how to reference the ORIGINAL MainForm, the one that was created in the Main method. Thanks in advance...
This will work, but only when you have one instans of MainForm.
public class MainForm : Form
{
public MainForm()
{
Instance = this;
}
public static MainForm Instance { get; private set; }
// Function to output results to main Listbox window
public void TextToBox(string aString)
{
// Place messages in Main Display list box window
this.listBox1.Items.Insert(0, aString);
}
}
public class Other
{
public void AddTextToListBox()
{
MainForm.Instance.TextToBox("Test");
}
}
...Edit...
Alternative:
class Program
{
public static MainForm MainFormInstance;
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MainFormInstance = new MainForm();
Application.Run(MainFormInstance);
}
}
public class Other
{
public void AddTextToListBox()
{
Program.MainFormInstance.TextToBox("Test");
}
}
I would just pass a delegate to the other class.
/* this runs (previous code was not guaranteed to run) */
class OtherClass
{
public delegate void TextToBox(string s);
TextToBox textToBox;
int next = 0;
public OtherClass(TextToBox ttb)
{
textToBox = ttb;
}
public void SendSomeText()
{
textToBox(next.ToString());
next++;
}
}
I'm assuming you'll be instantiating OtherClass from MainForm. Is this how you're calling "OtherClass"?
public partial class MainForm : Form
{
OtherClass otherClass;
public MainForm()
{
/* just two controls -- listBox1 and button1 */
InitializeComponent();
otherClass = new OtherClass(this.TextToBox);
}
public void TextToBox(string aString)
{
listBox1.Items.Add(aString);
}
private void button1_Click(object sender, EventArgs e)
{
otherClass.SendSomeText();
}
}
On a button click the next numeric value is added at the beginning of the ListBox. You'll have to post some of your code if you need further help.
alternatively you could use a singleton pattern, or static methods and make sure you include the class in a 'using' statement at the top of your program