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
Related
Problem: I want to write the same message to a textbox control that I am writing to a log file.
I have a windows form (Form1.cs) that calls a crosscutting class of static methods. In each of the crosscutting methods, they call WriteLogEntry to update a log file of what they are doing. I'd like to send back an event to Form1 so I can write the same log message to a control on the form.
I have looked at events but do not understand enough to make sense of the examples and have not found a simple enough example to do what I want. Can someone show me a simiple example of how to add an event to my code to accomplish this?
namespace MainForm
{
public delegate void MyDel(string str);
public partial class Form1 : Form
{
public event MyDel MyEvent;
public Form1()
{
InitializeComponent();
MyEvent += new MyDel(WriteSomething);
Crosscutting.DoSomething();
}
public void WriteSomething(string message)
{
Console.WriteLine(message);
}
}
//Crosscutting.cs
public class Crosscutting
{
private static void WriteLogEntry(string message)
{
// Code to write message to log file.
}
public static void DoSomething()
{
WriteSomething obj = new WriteSomething();
// Code to do something.
WriteLogEntry("I'm doing something");
}
}
}
After not being able to figure out how to use a delegate to get back to the form, I tried another way. By creating an instance of Form1 on "MyClass", I was able to use a public method to write back to the form. Not the way I wanted, but it is a way to get it done for now. If anyone can explain how to do this a better way, please do so.
public partial class Form1 : Form
{
private string message = string.Empty;
public static Form1 form;
public Form1()
{
InitializeComponent();
form = this;
}
public void UpdateTextBox(string message)
{
textBox1.Text += message + Environment.NewLine;
this.Update();
}
private void button1_Click(object sender, EventArgs e)
{
var myClass = new MyClass();
myClass.DoSomething();
}
}
public class MyClass
{
public void DoSomething()
{
Log("I did something");
}
private void Log(string message)
{
Console.WriteLine(message);
Form1.form.UpdateTextBox(message);
}
}
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);
}
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");
}
}
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