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");
}
}
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());
}
}
I have to called a method Run in the Class1. And now I try to return str to listbox Running. I know this code Running.Items.Add(str); is not correct because it is in a different class. Please tell me how to fix it?
Class1.cs
class Class1
{
public void Run()
{
string str = "Hello";
Running.Items.Add(str);
}
}
Form1.cs
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Running_SelectedIndexChanged(object sender, EventArgs e)
{
}
}
Update How do I call a class method
Form1
public void Invoke(string typeName, string methodName)
{
Type type = Type.GetType(typeName);
object instance = Activator.CreateInstance(type);
MethodInfo method = type.GetMethod(methodName);
method.Invoke(instance, null);
}
private void Start_Click(object sender, EventArgs e)
{
new Task(() => { Invoke("Worker." + name, "Run"); }).Start();
}
You don't show how you call Run(), so I'm going to assume you do so from Form1.
You need to pass a reference one way or the other. Making your class Class1 dependent on your form is a bad idea. You can make it dependent on the lsitbox, and rename it accordingly:
public class ListBoxAdder()
{
private ListBox _listBox;
public ListBoxAdder(ListBox listBox)
{
_listBox = listBox;
}
public void Run()
{
string str = "Hello";
_listbox.Items.Add(str);
}
}
Then call it from your form and pass the reference to the Running ListBox:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var listBoxAdder = new ListBoxAdder(this.Running);
listBoxAdder.Run();
}
}
If you want to add the str object to the Running list in the class class1 you should just get a reference to the active form of the Form1 :
public void Run()
{
string str = "Hello";
((Form1)Form1.ActiveForm).Running.Items.Add(str);
}
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
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