Calling method from different namespace and class - c#

I'm trying to put some stuff that I use a lot into separate classes so it's easier to implement when starting a new project.
One of the things that I would like to do, is dynamically create a statusbar on my mainform. I have done this in a previous project and there it worked fine. So I copied the code and I changed the NameSpace for the mainform.
When I run the code it stops at the line
MainForm.Controls.Add(status);
When I look, it says Mainform is null.
Other than the Namespace I haven't changed anything.
Does anybody have an idea why this is happening?
Thanks
Kenneth
//THIS IS THE SEPARATE CLASS
public class Tools
{
public Form MainForm;
public void setupForm()
{
// LINK THE FORM
MainForm = myNamespace.Form1.MainForm;
// CREATE A STATUSBAR
StatusStrip status = new StatusStrip();
status.Name = "status";
// I'VE REMOVED SOME OF THE DYNAMIC CREATION STUFF FOR READABILITY
// ADD THE STATUSSTRIP TO THE FORM
MainForm.Controls.Add(status);
}
//THIS IS THE MAINFORM
public static Form1 MainForm;
public myNameSpace.Tools tools;
private void setupForm()
{
this.KeyPreview = true;
// LINK THE TOOLS CLASS
tools = new myNameSpace.Tools();
// SETUP THE FORM
tools.setupForm();
}

You have to pass a refernece of your main form to the Tools class. You can do this when you initialize tools or when you call the method setupForm. I implemented the second possibility for you:
//the call:
tools.setupForm(this);
//the implementation of the method
private void setupForm(Form1 MainForm)
{
//your method code
}

The normal way to separate responsibility is to inject the object you want to affect - not hijack it with a hardcoded reference.
Try injecting the form when you create your tools object:
tools = new myNameSpace.Tools(this);

Its null because you don't initiate or have a refference to the main window. You just create an alias for the namespace but not for the instance.
Pass the mainWondow as a parameter to the setupForm function. Then it will work.

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.

C# - Call a function in a parent form

I'm trying to call a function in a main form from another form... Already got to call a simple function, by declaring it public static in main form, yet I can't call the needed one.
The function to call:
public static void spotcall()
{
string dial = Registry.CurrentUser.OpenSubKey("SOFTWARE").OpenSubKey("INTERCOMCS").GetValue("DIAL").ToString();
MainForm.txtSendKeys.Text = dial;// Here it asks me for a reference to an object.
foreach (char c in txtSendKeys.Text)
{
sideapp.Keyboard.SendKey(c.ToString(), checkBoxPrivate.Checked);
}
txtSendKeys.Clear();
}
The procedure I use to call it from a child form:
private void button1_Click(object sender, EventArgs e)
{
button1.Text = "Hoho";
MainForm.spotcall();
}
I completely admit that I lack some theory about C#, but as it often happens, I just have to do it for my work, so I expect to get help if by chance I don't get to the solution by myself. Thank you :)
You cannot reference instances of controls on your MainForm in a static method. Like the compiler is telling you, you need an instance of the form in order to update things like TextBoxes. Without an instance, where would the values you are trying to update go?
I'm not sure exactly how the child form is being created, but one way you could call methods on your MainForm would be to provide a reference to your MainForm instance directly to the child form. This could be through the constructor or some public property.
For example
public class ChildForm : Form {
public MainForm MyParent { get; set; }
private void button1_Click(object sender, EventArgs e)
{
button1.Text = "Hoho";
// Now your child can access the instance of MainForm directly
this.MyParent.spotcall();
}
}
Assuming you are creating ChildForm inside of MainForm the code to give the child a reference is pretty simple:
var childForm = new ChildForm();
childForm.MyParent = this; // this is a `MainForm` in this case
childForm.Show();
You would also need to make spotcall an instance method and not a static method, and remove the static reference to MainForm in your code:
public void spotcall()
{
string dial = Registry.CurrentUser.OpenSubKey("SOFTWARE").OpenSubKey("INTERCOMCS").GetValue("DIAL").ToString();
// Now it no longer asks you for a reference, you have one!
txtSendKeys.Text = dial;
foreach (char c in txtSendKeys.Text)
{
sideapp.Keyboard.SendKey(c.ToString(), checkBoxPrivate.Checked);
}
txtSendKeys.Clear();
}
I think the correct way to do this is to use delegates. This way your form (window) does not have to know anything about the parent form (the form can be opened from different parent forms).
Let's say we want to call a function in the parent form when the child form is closed (not showing the form as modal).
At the top of your child form create a delegate:
public delegate void CloseEvent();
public CloseEvent WindowClosed;
Create the form closing event and have it call your delegate:
private void child_FormClosing(object sender, FormClosingEventArgs e)
{
WindowClosed();
}
A button in the parent form can show the child form and set the callback:
private ChildForm childform = null;
private void buttonShowChildForm_Click(object sender, EventArgs e)
{
if (childform == null)
{
childform = new ChildForm();
childform.WindowClosed += childClosed;
childform.Show();
} else
{
childform.BringToFront();
}
}
private void childClosed()
{
childform = null;
}
In this example we use a button to open a new form that does not block the parent form. If the user tries to open the form a second time, we just bring the existing form to the front to show it to the user. When the form is closed we set the object to null so that next time we click the button a new form is opened because the old was disposed when closed.
Best regards
Hans Milling...
You can not access non-static members in static context, which means you have to made txtSendKeys static, or make your function non-static.
If you create a static function, you may not reference global variables inside the function that aren't static as well.
So in order for spotcall to be static, you have to remove the reference to the txtSendKeys (I'm assuming this is a text box that you have created elsewhere in the form) or txtSendKeys must be declared within the static function.
Additional:
You obtained the value for txtSendKeys.Text in the previous line, via variable dial. Instead of referencing txtSendKeys.Text at all, I imagine you could simply use the variable dial to complete the function and leave the function static (you clear it at the end anyway).
public static void spotcall()
{
string dial = Registry.CurrentUser.OpenSubKey("SOFTWARE").OpenSubKey("INTERCOMCS").GetValue("DIAL").ToString();
foreach (char c in dial)
{
sideapp.Keyboard.SendKey(c.ToString(), checkBoxPrivate.Checked);
}
}
Although, that wouldn't overcome the same issue you would likely run into with checkBoxPrivate.Checked.
You could change it to take a boolean argument.
public static void spotcall(Boolean PrivateChecked)
{
string dial = Registry.CurrentUser.OpenSubKey("SOFTWARE").OpenSubKey("INTERCOMCS").GetValue("DIAL").ToString();
foreach (char c in dial)
{
sideapp.Keyboard.SendKey(c.ToString(), PrivateChecked);
}
}
You can put the shared code in a third class that's visible to both forms. So, for example:
public class static HelperFunctions
{
public static void spotcall()
{
. . .
}
}
Then replace
MainForm.spotcall()
with
HelperFunctions.spotcall()
The MainForm is just a class. It has the structure of the class. But the only data you can get from it is static data.
But an instance of that class appears when you do: MainForm MyFormInstance = new MainForm();
The MainForm can be used only to access static members (methods, properties...).
When you want to get the txtSendKeys, you must get it from an instance (object reference). That's because the textbox is not static, so it only exists in instances of the form.
So, you should do the following:
Make spotcall NOT static.
Put in child form a variable MainForm MyParentMainForm;
When you call the child, set that MyParentMainForm with the instance of the mainform. If it's being called from the main form, you can get the instance with the this keyword.
Inside child form, call MyParentMainForm.spotcall
PS: I'm not sure if there's something like a real child form or if you just call new forms from another. If there's really a child form, you can get the Parent property to access the instance of the main form.
This is sort of a "design pattern" issue, which I'll elaborate on, but I can try to explain the most direct way to solve this if you don't expect this program to change very much. "Static" things only exist once - once in the entire application. When a variable or function is static, it's much easier to access from anywhere in the program; but you can't access an object's associated data, because you're not pointing to a particular instance of that object (ie, you have seven MainForms. Which one are you calling this function on?) Since standard WinForm design expects you could have seven copies of MainForm displaying, all variables associated are going to be instance variables, or non-static. However, if you expect never to have a second MainForm, then you can take the "singleton" approach, and have an easy way of accessing your one instance.
partial class MainForm {
// only including the code that I'm adding; I'm sure there's a lot of stuff in your form.
public static MainForm Instance { public get; private set; }
protected void onInitialize() { // You need to hook this part up yourself.
Instance = this;
}
}
partial class SubForm {
protected void onImportantButton() {
MainForm.Instance.doImportantThing()
}
}
Putting too much active data-changing logic in form classes is a pretty common issue with many beginners' code. That's not a horrible thing - you wouldn't want to be making 5 controlling classes just for a simple thing you're trying. As code gets more complex, you start to find some things would make more sense to move to a "sublevel" of classes that don't interact with the user (so, some day, if this is being re-coded as a server program, you could throw away the form classes, and just use the logic classes - theoretically speaking). It also takes some time for many programmers to understand the whole concept of object "instances", and the "context" that a function is called in.

Showing a hidden form

How do i show a from that have been hidden using
this.Hide();
I have tried
MainMenuForm.Show();
and this just says i need an object ref. I then tried:
MainMenuForm frmMainMenu = new MainMenuForm();
frmMainMenu.Show();
Which seems to show the appropriate form. But when you exit the app, it is still held in memory because it hasn't shown the form that was hidden, instead it has shown a new version of the form. In effect having 2 instances of the form (one hidden, one visible).
Just to clarify, the MainMenuForm is the startup form. When (for example) Option 1 is clicked, the MainMenuForm then hides itself while opening up the Option 1 form. What i would like to know is how to i make the Option 1 form that the MainMenuForm opens "unhide" the MainMenuForm and then close itself.
What's the correct procedure here?
Thanks in advance.
When you do the following:
MainMenuForm frmMainMenu = new MainMenuForm();
frmMainMenu.Show();
You are creating and showing a new instance of the MainMenuForm.
In order to show and hide an instance of the MainMenuForm you'll need to hold a reference to it. I.e. when I do compact framework apps, I have a static classes using the singleton pattern to ensure I only ever have one instance of a form at run time:
public class FormProvider
{
public static MainMenuForm MainMenu
{
get
{
if (_mainMenu == null)
{
_mainMenu = new MainMenuForm();
}
return _mainMenu;
}
}
private static MainMenuForm _mainMenu;
}
Now you can just use FormProvider.MainMenu.Show() to show the form and FormProvider.MainMenu.Hide() to hide the form.
The Singleton Pattern (thanks to Lazarus for the link) is a good way of managing forms in WinForms applications because it means you only create the form instance once. The first time the form is accessed through its respective property, the form is instantiated and stored in a private variable.
For example, the first time you use FormProvider.MainMenu, the private variable _mainMenu is instantiated. Any subsequent times you call FormProvider.MainMenu, _mainMenu is returned straight away without being instantiated again.
However, you don't have to store all your form classes in a static instance. You can just have the form as a property on the form that's controlling the MainMenu.
public partial class YourMainForm : Form
{
private MainMenuForm _mainMenu = new MainMenuForm();
protected void ShowForm()
{
_mainMenu.Show();
}
protected void HideForm()
{
_mainMenu.Hide();
}
}
UPDATE:
Just read that MainMenuForm is your startup form. Implement a class similar to my singleton example above, and then change your code to the following in the Program.cs file of your application:
Application.Run(FormProvider.MainMenu);
You can then access the MainMenuForm from anywhere in your application through the FormProvider class.
The simplest and easiest way is to use LINQ and look into the Application.OpenForms property. I'm assuming you have only 1 instance of the form (hopefully!), otherwise make sure to have to have some public property on the hidden form to be able to differentiate it.
The following code will un-hide the form for you:
var formToShow = Application.OpenForms.Cast<Form>()
.FirstOrDefault(c => c is MainMenuForm);
if (formToShow != null)
{
formToShow.Show();
}
You need to keep a reference to the first form when it's created and then the code that holds that reference can call Show on it.
If you don't open that form from somewhere but it's set as the startup form, then you either need to change it so that you have a Main method that opens that form or you can have that form store a reference to itself somewhere that can be accessed from other places.
For example, an quick and ugly way would be to, add a public static property to your mainform and then when you hide the form it also writes this to that property which can then be retrieved when needed by other parts of the code.
Practically This works for me....
public class MainWindow : Form
{
Form _mainMenuForm = new MainMenuForm();
}
calling it through a button click event.
private void buttonclick()
{
if (_mainMenuForm.Visible)
{
_mainMenuForm.Visible = false;
}
else
{
_mainMenuForm.Visible = true;
}
}
Store a reference to the form and call .Hide() and .Show() on that.
For example:
public class MainWindow : Form
{
private Form _mainMenuForm = new MainMenuForm();
public void btnShowMenuForm_Click(...)
{
_mainMenuForm.Show();
}
public void btnHideMenuForm_Click(...)
{
_mainMenuForm.Hide();
}
//etc
}
This example assumes you have a form which is launching the MainMenuForm.
Call the referenced form.
Like:
Calling parent
----------
public MyForm f {get;set;}
void DoStuff()
{
f = new MyForm();
f.Show();
}
MyForm
----------
void DoOtherStuff()
{
this.hide();
}
Parent
----------
void UnHideForm()
{
f.show();
}
Another simpler method to achieve this is to loop through the open forms to see which are still running and open it...
foreach (Form oForm in Application.OpenForms)
{
if (oForm is MainMenuForm)
{
oForm.Show();
break;
}
}

C#: How to access a button outside the form class

I want to either enable or disable a button from another file,what should I do?
This is the form class declaration:
public partial class Form1 : Form
I tried with
Form.btnName.enabled = false/true
but there's no btnName member.
Thanks in advance!
Simply expose a public method:
public void EnableButton(bool enable)
{
this.myButton.Enabled = enable;
}
Correction:
public void EnableButton()
{
this.myButton.Enabled = true;
}
You need to expose the btnName member to other classes by making it public or using a property of sorts. For example add the following code to Form1
public Button ButtonName { get { return btnName; } }
Now you can use form.ButtonName for any instance of Form1
I really suggest to read more information on how forms fit in .net. You have a couple issues in that sample code "Form.btnName.enabled = false/true"
Your form is called Form1, it inherits from Form.
Forms are instances, in fact you can have different form instances in an application belonging to the same class.
Because of the above, it would not make sense to access Form1.btnName. You have to do it through the specific instance.
Form's controls are not public by default, define a method for that.
Windows forms projects, usually have a main that runs the form. There you can access the form instance and hand it to something else in the app.
The above answers the specific question. Note that there are multiple ways to achieve different scenarios, and what you really want to do might not need the above approach.
This is because by default, the controls on a form are not public (unlike in VB6 which all controls were exposed publicly).
I believe you can change the visibility accessor in the designer to public, but that's generally a bad idea.
Rather, you should expose a method on your form that will perform the action on the button, and make that method accessible to whatever code you want to call it from. This allows for greater encapsulation and will help prevent side effects from occurring in your code.
You'll have to specify it on your specific instance of Form1.
Ie: If you have something like Form1 myForm = new Form1(...);, then you can do myForm.btnName.Enabled = false;
This will also require that btnName is public. It would be "better" to make a property or accessor to retrieve it than directly provide public access to the, by default, private button field member.
You need to add a public property, or method to set the button.
public void DisableBtnName()
{
this.btnName.Enabled=false;
}
public Button BtnName
{
get { return this.btnName;}
}
In Form1, create a object for external class(add button name in the parameter)
Class1 obj_Class1 = new Class1(btnName);
In Class1 , create a private button
private System.Windows.Forms.Button btnName;
In Class1 Construct
public Class1(System.Windows.Forms.Button btnName)
{
this. btnName = btnName;
}
then you can access your button like,
btnName.enabled = false/true;

C# Winforms: How to get a reference to Form1 design time

I have a form that has a public property
public bool cancelSearch = false;
I also have a class which is sitting in my bll (business logic layer), in this class I have a method, and in this method I have a loop. I would like to know how can I get the method to recognise the form (this custom class and form1 are in the same namespace).
I have tried just Form1. but the intellisense doesn't recognise the property.
Also I tried to instantialize the form using Form f1 = winSearch.Form1.ActiveForm; but this too did not help
Any ideas?
When you are calling the business logic that needs to know the information pass a reference of the form to the method.
Something like.
public class MyBLClass
{
public void DoSomething(Form1 theForm)
{
//You can use theForm.cancelSearch to get the value
}
}
then when calling it from a Form1 instance
MyBlClass myClassInstance = new MyBlClass;
myClassInstance.DoSomething(this);
HOWEVER
Really you shouldn't do this as it tightly couples the data, just make a property on your BL class that accepts the parameter and use it that way.
I think you should look at how to stop a workerthread.
I have a strong feeling that you have a Button.Click event handler that runs your business logic and another Button.Click that sets your cancelSearch variable. This won't work. The GUI thread which would run your business logic, won't see the other button being clicked. If I'm right you should very much use a worker thread.
Your question is really not clear. You might want to edit it.
Advice
The form shouldn't pass to your business logic layer...
Solutions to your problem
BUT if you really want to (BUT it's really not something to do), you need to pass the reference. You can do it by passing the reference in the constructor of your class, or by a property.
Method with Constructor
public class YourClass
{
private Form1 youFormRef;
public YourClass(Form1 youFormRef)
{
this.youFormRef = youFormRef;
}
public void ExecuteWithCancel()
{
//You while loop here
//this.youFormRef.cancelSearch...
}
}
Method with Property
public class YourClass
{
private Form1 youFormRef;
public int FormRef
{
set
{
this.youFormRef = value;
}
get
{
return this.youFormRef;
}
}
public void ExecuteWithCancel()
{
//You while loop here
//this.youFormRef.cancelSearch
}
}
As the other (very quick) responses indicate, you need to have an instance variable in order to get your intellisence to show you what you need.
Your app by default does not have a reference to the main form instance, if you look at your program.cs file you will see that the form is constructed like so...
Application.Run(new Form1());
so you have a couple options, you could create a global var (yuck) and edit your program.cs file to use it..
Form1 myForm = new Form1();
Application.Run(myForm);
Pass a reference to the business object from your running form like some others have suggested
myBusinessObj.DoThisThing(this);
or find your form in the Application.OpenForms collection and use it.

Categories