I have a multi-page program which changes its displayed elements by changing its visibility, which is written in the mainForm class(renamed from Form1) . Now as my program is getting more and more complicated I was thinking to make some kind of an external class in wich all these states would be changed becouse i have 26 text boxes and 3 options of displaying them which means I have 78 lines of textBox1.visibility = true; lines.
I have tried creating a class and changing the modifiers of all the textboxes to public and created an instance of form1 in my interfaceClass (MainForm mainform = new MainForm();) but this does totally not change anything to my form at all although no syntax or runtime errors happen.
I just want maybe some suggestions on how this can be realized if it can be at all.
You don't need a separate class for this; just write a single method in your form called CheckVisibility() and call that wherever you need to make sure your controls are shown or hidden properly. Include all of the necessary conditions and show/hide changes in that method.
Set the control to public in the designer:
public System.Windows.Forms.Button button1;
Create a new class and for example rename it to exampleClass
public class exampleClass
{
public static Form1 frm;
public static void HideButton()
{
frm.button1.Visible = false;
}
}
Add this after Form1 InitializeComponent:
exampleClass.frm = this;
Now you can hide the button from anywhere you want:
exampleClass.HideButton();
Related
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.
For example after creating a new Windows Form project I have my class called Form1.cs and from that form I can simply start typing the name of a form control and it will auto populate the form control variable names and I am able to use them in the class. However I have other classes that need to be able to access these form control variables as well, but they are not accessible.
Make them public if they are going to be used in another assembly, or internal if they are going to be used in the same project. Making them static means you don't have to pass your Form1 into the other classes.
Example... Say your Form1 has a string that contains the text you display in the title bar. Making it internal static, like this:
internal static readonly string MsgBox_Title = " Best Application Evar!";
lets you access it from other classes like this:
Form1.MsgBox_Title
It doesn't have to be readonly; that's just an example I pulled from an old app...
If you don't want static variables, you'll have to pass in an instance of Form1.
public class SomeClass
{
private Form1 m_Form1;
public SomeClass(Form1 form1)
{
m_Form1 = form1;
}
private void someMethod()
{
string localValue = m_Form1.SomeMemberStringVariable;
}
}
It's a very contrived example, but hopefully you get the idea.
If you want to call the Refresh method from a class instantiated from Form1, you could use an event in the child class to notify Form1.
Example:
This Form1 has a button that I use to show a secondary form.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnShowPopup_Click(object sender, EventArgs e)
{
PopupForm f = new PopupForm();
f.CallRefreshHandler += PopupForm_CallRefreshHandler;
f.ShowDialog();
}
private void PopupForm_CallRefreshHandler(object sender, EventArgs e)
{
Refresh();
}
}
The secondary form, "PopupForm", has a button that I use to raise an event that the Form1 is subscribed to, and lets Form1 know to call Refresh.
public partial class PopupForm : Form
{
public event EventHandler CallRefreshHandler;
public PopupForm()
{
InitializeComponent();
}
private void btnRaiseEvent_Click(object sender, EventArgs e)
{
EventHandler handler = CallRefreshHandler;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
Hope this helps.
Create an object of that class & start using those variables like this
Form1 fm = new Form1();
string abc = fm.VAR;
Define a public property in your form.
public string MyProp { get; set; }
Form1 frm = new Form1();
frm.MyProp = "Value";
Or define the property as static to avoid having to instantiate Form1:
public static string MyProp { get; set; }
Form1.MyProp = "Value";
I ran into this issue recently. I was keeping some methods in a separate class. Maybe not a good design decision in my case, I'm not sure yet. And these methods sometimes needed to communicate with controls in the main Form1. For example, to write to textBox1.
Turns out easy enough. Just write your method signature to include a TextBox instance. For example you pass textBox1 in and inside the method you refer to it as tb. Then when you call that method (even though it is in another class) you set the tb.Text property to whatever you like and it will show on textBox1.
This makes sense when you consider that control is just a special kind of object, graphically represented in the Form. When you pass it as an argument to a method in another class or the same class, you are actually passing the reference. So writing text to it in the method call will write text to the original control.
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;
}
}
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;
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.