A global function to be executed before opening a form - c#

I have around 15 forms and every form includes some similar piece of codes.
What i want to know is that there is any way to automatically call a function containing that particular piece of code when a form is opening?
Like, lets say i want to show Hello World message every time when any form of a project is loaded.
So what i can do is i can create a module or class file and i can add a piece of code their and i can call it in every form.
But this i don't want, what i want is that, is there any way where i can add this piece of code and automatically it gets populated/triggered when a form gets loaded.
Maybe we can call it something like - auto calling function for forms
Like, whenever a form is opening automatically a class or function gets called without defining it in the particular form. Maybe a library kind of thing which will be called anyways when a form is loaded and i can add my piece of code there and it gets executed.

Create your own base class inheriting from form:
public abstract class FormBase : Form { /*...*/ }
Then every form you are using may inherit from this base class:
public class MyForm : FormBase { /*...*/ }

You can add an event handler to the form, and put whatever code needs to be run in there.
For Example:
this.Load += new System.EventHandler(this.FormName_Load);

public class frm_Base : Form
{
public void frm_Base()
{
this.Load += new System.EventHandler(this.frm_Base_Load);
}
public void frm_Base_Load(object sender, EventArgs e)
{
OnFormLoad();
}
public virtual OnFormLoad()
{
MessageBox.Show("Hello World");
}
}
public class frm_Derived : frm_Base
{
public override OnFormLoad()
{
base.OnFormLoad();
MessageBox.Show("Another Hello From Derived");
}
}
You can now inherit the functionality that happens on load in all of your other forms as well as do other things too by making your load method virtual.

Related

Window form textbox not updating from another file

I have two files, form1.cs and parser.cs. When I called my update method for NPCLogger.Text in the form1.cs file it works. but when I call it from parser.cs it does not? I've tried a lot of other solutions online and can't seem to get it working.
form1.cs
public void updateConsole(string text)
{
NPCLogger.Text += text;
}
private void ParseButton_Click(object sender, EventArgs e)
{
Parser parser = new Parser();
string link = UserLink.Text;
parser.Parsing(link);
updateConsole("12312"); // this works
}
parser.cs
public class Parser : Form
{
public bool debug = false;
public string aggroRadius = null;
public void Parsing(string userLink)
{
updateConsole("This does not work");
The compiler error you're seeing (but not including in the question...) is telling you that there is no updateConsole method in the Parser class. (Unless you've added one, and didn't include that in the question. In which case... what on Earth does that method do and why are you expecting a method on a different class to be invoked?)
When you attempt to call a method that's in the Parser class from the Form1 class, note how you do that:
parser.Parsing(link);
You don't just call Parsing(link) by itself, you call it on the parser variable, which is an instance of the Parser class. So, when you want to call a method that's in the Form1 class from the Parser class, why do you expect it to be any different?
You need a reference to your Form1 object. Given the code shown, probably the simplest way is to add it to the Parser constructor:
private Form1 form1Instance { get; set; }
public Parser(Form1 form1)
{
this.form1Instance = form1;
}
And pass the reference when calling the constructor:
Parser parser = new Parser(this);
Then, in Parser, you can use that property to reference the object:
this.form1Instance.updateConsole("This does not work");
As an aside... You're digging yourself into a rabbit hole. Now you have two forms trying to directly interact with each other's UI controls. It's going to get unwieldy quickly.
A form should be responsible for its own UI controls. Models/objects (not forms) should encapsulate the core logic of the application. Any given form would invoke that logic and use the returned result to update its UI.

Passing Variable from another class into a form

I am struggling with passing a Variable (a string) in C# for a special problem:
Overview:
I am writing a plugin for a purchased program at my company. The program (or better: the programs support) gives the user basic C#-Code which basically just opens a form, and connects the program with whatever I write down in the forms code.
As it is a Visual-Studio-Solution I get some files: "MyUserInterface.cs" and "MyUserInterface.Designer.cs".
"MyUserInterface.Designer.cs" defines the look of my form, i thing the most importand parts for my problem are:
partial class MyUserInterface
{
[...]
private void InitializeComponent()
{
[...]
this.f_status = new System.Windows.Forms.Label();
this.SuspendLayout();
[...]
//
// status
//
this.f_status.Name = "status";
this.f_status.Text = "WELCOME TO MYPLUGIN v2";
[...]
this.Controls.Add(this.f_status);
this.ResumeLayout(false);
this.PerformLayout();
}
[...]
private System.Windows.Forms.Label f_status;
[...]
}
The most important code from "MyUserInterface.cs" is:
partial class MyUserInterface
{
[...]
public MyUserInterface()
{
InitializeComponent();
}
[...]
private void click_compute(object sender, EventArgs e)
{
//Basically everythings runs here!
//The code is opend in other classes and other files
}
}
Now as i marked in the code section, my whole code runs in the "click-compute" Function and is "outsourced" into other classes.
One important part of my code is found in "statushandler.cs":
class statushandler
{
[...]
public static void status_msg(string c_msg)
{
[...]
f_status.Text = c_msg; // And here is my problem!!
[...]
}
}
Problem:
In my special case, i try to change the text of the "f_status"-Lable while running my code by using the "status_msg" Function!
While I pass variables between classes a few times in my code. A cannot figure out, why this explicit one cant be found inside "statushandler". (It is no problem as long as I stay inside the original "click_compute", without going into a different class).
What I already tried:
1.) I tried to change basically everything in "MyUserInterface" into "public",
2.) Also I tried to call f_status in status_msg like MyUserInterface.f_status.Text,
3.) Write a Getter/Setter-Function in "MyUserInterface.(Designer.)cs" (both), which was catastrophic because i couldn't define the Label in the InitializeComponent anymore.
4.)
a.)Read a lot of Stackoverflow-Threads about passing variables between classes, which all didn't helped, all solutions I found, are working between classes, but not in this special case.
b.)Watched a lot of youTube tutorials, same result.
c.)Read some stackoverflow-Threds about passing variables between different Forms, but they all had in common, that the "displaying-form" was opend AFTER the variable was known. In my special case the form is opened all the time, and can't be closed, nor reopened...
And now I am out of ideas!
I wouldn't be surprised, if I do not see some details, but I can't found them... I would be very happy, when somebody could help me!
My question:
How can I change the text of my lable from another class?
Your method is static while your form has instance. So your static method does not know anything about your form. You can add MyUserInterface parameter to static method
public static void status_msg(MyUserInterface form, string c_msg)
{
[...]
form.f_status.Text = c_msg; // And here is my problem!!
[...]
}
If you have single instance form (only one instance is created at a time) you can have static property with it's reference:
partial class MyUserInterface
{
public static MyUserInterface Instance { get; private set; }
[...]
public MyUserInterface()
{
InitializeComponent();
Instance = this;
}
}
With this solution you can use your old method:
class statushandler
{
[...]
public static void status_msg(string c_msg)
{
[...]
MyUserInterface.Instance.f_status.Text = c_msg; // You have instance of yout form here
[...]
}
}
Of course you should protect against null/ Disposed form etc.
Create a public property on the specific class in your 1st Form that gets the label's value like this:
public string Name {get {return Label1.Text}; set {Label1.Text = value}; }
Then in your 2nd Form:
public Form2(Form1 form)
{
string name;
name = form.Name;
}

Close form currently in focus

I was wondering how you would close the Form that is currently in focus or the one which a control is contained in. For example, I have an imported header with a menu that I import into all forms in my application.
This is the (simplified) code in my Header class:
public static Panel GetHeader()
{
...
menuItem.Text = "Menu Item";
menuItem.Name = "Next form to open";
menuItem.Click += toolStrip_Click;
...
}
public static void toolStrip_Click(object sender, EventArgs e)
{
ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
NavigationClass.SaveNextForm(menuItem.Name);
}
The navigation class is just something I made which will select the next form to open but I couldn't find anything to then close the current one (since Close() isn't an option due to it being imported with Controls.Add(HeaderClass.GetHeader))
Edit
Just to make clear, this form is in another file which is just a normal class file. That's where the difficulty lies because I'm trying to avoid a severe violation of the DRY principle
Don't use static handlers as #Hans Passant suggests. That is important.
Try sending your main form to your class as a parameter, and store it in that class. This can be done either when you are instantiating your class, or after that. Then, when you need to close the form, call it's Close method. Since you don't include your codes in more details, here is my example with some assumptions.
public class MainForm : Form
{
private HeaderClass HeaderClass;
public MainForm()
{
HeaderClass = new HeaderClass(this);
}
}
public class HeaderClass
{
private MainForm MainForm;
public HeaderClass(MainForm mainForm)
{
MainForm = mainForm;
}
public void MethodThatYouNeedToCloseTheFormFrom()
{
...
MainForm.Close();
...
}
}
Let us know if you require any more elaboration.

How to get a method on a main form to get executed on the main form whenever i do some action on a secondary form?

I'm trying to update my data on a main form whenever I change some option in a secondary form.
Possible solution:
Make the method public on Form1 (the main form) like this:
public void updatedata()
{
//data update
}
And then call it on the secondary form:
Form1.updatedata()
This doesn't work and I believe it's because he is trying to update the Form2
I'm using partial classes, but I'm not very well versed on them.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
And the secondary one:
public partial class formOpConfig : Form
{
private Form1 Opener { get; set; }
public formOpConfig(Form1 opener)
{ //initialize component
}
}
I feel like surely there is a duplicate question to match this one. But I have been unable to find it.
Given the code you posted, your attempt probably would have worked had you used Opener.updatedata() instead of Form1.updatedata(). But that still would not have been the best solution.
Commenter John Saunders is correct, the right way to do this is to declare an event in formOpConfig, and then have Form1 subscribe to it. That looks more like this:
public partial class formOpConfig : Form
{
public event EventHandler UpdateData;
private void SomethingHappens()
{
// do stuff...
OnUpdateData();
// maybe do other stuff too...
}
private void OnUpdateData()
{
EventHandler handler = UpdateData;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
The above declares an event, and raises that event (invokes the handlers) at the appropriate time (i.e. when SomethingHappens()).
public partial class Form1 : Form
{
private void OpenConfigForm()
{
OpenConfigForm opConfig = new formOpConfig();
opConfig.UpdateData += (sender, e) => updatedata();
}
// Note that this method is private...no one else should need to call it
private void updatedata()
{
//data update
}
}
Here, Form1 subscribes to the event when it creates the instance of formOpConfig (I am assuming Form1 is what creates that instance), and when its handler is invoked, it calls the updatedata() method you've already written.
In this way, the two classes remain decoupled; i.e. they are not actually dependent on each other, more than they need to be (in particular, the formOpConfig class doesn't need to know anything about Form1).
A good way to do this is to use an Event.
This allows you to decouple the forms because they do not even need a reference to each other; basically an event is a way for your second form to tell whoever might be listening (without having to exactly know who) that something of interest happened, and to give them some information about that interesting event that they can use.
The linked article will give you much more detail than the below, which is just a quick idea of how to do it; I would recommend working through the tutorial!
The mechanism by which this occurs is that anyone who wants to know about interesting events on Form2 has to subscribe to the corresponding event on Form2; then whenever Form2 wants to tell its listeners that something has happened, it invokes any event handlers that have been attached to the event.
Because an event can have multiple handlers, it's a really excellent way to keep components in your application decoupled.
Quick demo
(note: code below is off top of head so not tested, no error handling, etc.)
First of all, you need to declare a class that can be used to send the interesting data to listening parties. This class has to inherit from System.EventArgs
public class InterestingEventArgs:EventArgs
{
public string AnInterestingFact {get;private set;}
public InterestingEventArgs(string fact)
{
AnInterestingFact =fact;
}
}
It doesn't matter where you declare this as long as it's visible to both Form1 and Form2.
Next, you have to declare an event on Form2, it needs to be public and should look like this:
public event EventHandler<InterestingEventArgs> SomethingInterestingHappened;
Now you need to decide when you are going to tell interested parties about this event. Let's suppose you have a button on Form2 and you want to raise the event when you click it. So in the Click handler for the button, you might have code like this:
public void btnRaiseEvent_Clicked(object sender, EventArgs e)
{
var fact= txtFact.Text;
var handler = SomethingInterestingHappened;
if (handler!=null)
{
handler(this,new InterestingEventArgs(fact));
}
}
and finally here is how the code might look from Form1 when you are launching Form2, let's say you click a button on Form1 to launch Form2:
public void btnShowForm2_Clicked(object sender, EventArgs e)
{
var child = new Form2();
child.SomethingInterestingHappened+=OnSomethingInterestingHappened;
child.Show();
}
Finally you need to write an event handler on Form1 that will be called when the event is raised:
void OnSomethingInterestingHappened(object sender, InterestingEventArgs e)
{
MessageBox.Show("Did you know? " + e.AnInterestingFact);
}
It looks like you have passed in a reference to a Form1 object in the constructor. Use it:
public partial class formOpConfig : Form
{
private Form1 Opener { get; set; }
public formOpConfig(Form1 opener)
{
Opener = opener;
}
private void updateForm1()
{
Opener.updatedata();
}
}
Form1 is a class, not an object. You can say Form1.updatedata() if you make updatedata() a static method of the Form1 class, but that is probably not compatible with the rest of your code.

c# Accessing WinForm control properties from another class

How does one access WinForm controls such as ProgressBar properties from another class?
Please see my code below. I know this might not be the best option to expose WinForm class and its members as public but I am trying to clear the concept at this point.
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void button1_Click(object sender, EventArgs e)
{
Class1 c = new Class1();
c.loop();
}
public void PBSetup()
{
progressBar1.Minimum = 0;
progressBar1.Maximum = 100;
}
public void PBUpdate(int recno)
{
progressBar1.Value = Class1.recno;
}
}
}
namespace WindowsFormsApplication1
{
class Class1
{
public static int recno;
public void loop()
{
//How do I access Form1.PBSetup()??
for (recno = 0; recno <= 100; recno++)
{
//How do I access Form1.PBUpdate(recno)??
}
}
}
}
You do not want your business logic (your class) interacting with your UI (your form). The business logic should be agnostic of the presentation layer.
If you want the form to respond to things that happen inside the class, you could consider exposing an Event inside the class that the form could subscribe to, much like it would subscribe to a button's click event. The class instance could fire off the event completely unaware of who might be listening, and any subscribers would be notified.
This looks like a big time code smell :).
You would need an instance of Form1 inside of Class1 in order to PBUpdate.
Something tells me what you are doing is just not right.
Explain what you are trying to do and we can help. Otherwise there is no way to access PBUpdate unless you either made it a static function where you could call it like Form1.PBUpdate() or you had an instance of Form1 within your class Class1
You can change the access modifiers of the progress bar from private to Internal or public , you can do this operation from properties pane .
Keep in mind that you have to pass to the second class the instance of the form and then you can change the value of the progress bar directly from the second class.
However is a tricky solution, the best should be keep the presentation layer implementation separated and work with an event.
I do not recommend to use this method, for simple reason as mentioned here by one of the comments. But if you really want to access that form control, here is how:
1) Select that control and set its access modifier to internal.
2) Assume your form id is "Form1" and control id is "control1"
Inside your method:
Form1 form = (Form1)Application.OpenForms["Form1"];
// form.control1 should now be available.

Categories