I have a class for global variables, like this:
internal static class GlobalVariables
{
public static PortBrowserForm open;
}
The PortBrowserForm class is a Windows Form class that has a timer and want to use its properties, like this (in another form):
// In that other form...
GlobalVariables.open.timer1.Enabled = true;
But I cannot call it. I can only call a function from GlobalVariables.open variable (which is a form already). Please help.
GlobalVariables.open.timer1.Enabled = true;
To make the above code work you need to make the timer1's modifier public or atleast internal. But... Don't do that, never expose fields public because you don't get control over who is doing what.
Instead create a method which does the job for you.
class PortBrowserForm : Form
{
public void SetTimerEnabled(bool enabled)
{
timer1.Enabled = enabled;
}
}
Then use
GlobalVariables.open.SetTimerEnabled(true);
Quick and Dirty
Check PortBrowserForm .designer.cs/vb file there you can find the declaration of all controls of the form. Change its access level to public from there and you can access that from any form just by creating forms instance.
Update:
To access one forms control in another you need to pass the first form in the constructor of another. Suppose we have two forms
Form1.cs
Form2.cs
In some event of form1 , call form2.
frm1Btn_Click()
{
form2 f2 = new form2(this);
f2.Show();
}
Create a overloaded constructor in form2 with Form1 as parameter and pickup form1 and its all controls.
Related
I have a main form called FormMain.
FormMain has a RichTextBox inside of it called mainConsole.
I created a method inside of FormMain:
public void ConsoleAdd(String text)
{
mainConsole.AppendText(text);
mainConsole.AppendText(System.Environment.NewLine);
}
I changed the property Modifiers of mainConsole to Public.
Now in another class I wrote this in a button control:
FormMain fMain = new FormMain();
fMain.ConsoleAdd("Success!");
But it doesn't work. There is no exception raised, and there is no text added either.
Am I doing something wrong?
The problem I see is that you call ConsoleAdd on the wrong reference. It seems like you create a new reference of FormMain and call ConsoleAdd on this one. If you call
fMain.Show();
you would see a second window pop-up with the text in the RichTextBox. You have to pass the reference to the correct FormMain to the function trying to call ConsoleAdd or use a Singleton.
This is how I solved it:
In the FormMain I added this code:
static FormMain instance;
public FormMain()
{
InitializeComponent();
instance = this;
}
public static FormMain Instance
{
get
{
return instance;
}
}
And in the other class I called the method like this:
FormMain fMain = FormMain.Instance;
fMain.ConsoleAdd("Success!");
Thanks for the answers everybody!
I am trying to make a windows form to be reused across several projects. So I thought this would be a class library. What I want to do is call WindowsForm.Show() as a static call. I've tried to create a class library but I cannot reach the resources for an icon. I then created a WinForms project, but it wants a 'New' in the program.cs. I do not want to call
WindowsForm form = new WindowsForm()
form.show()
How do i create a reusable static form? I hope i'm being clear.
To add a factory method you can do:
public static MyForm ShowNew()
{
MyForm form = new MyForm();
return form;
}
About resources, it depends on what you're using the icon for. If the icon is always the same and it always will be, then add it to your library Properties/Resources (if you don't see it, go on your library project properties, on the tab Resources, and click add). Otherwise, add a parameter to your factory method (and to the form constructor as well) and pass it when you call the form:
public static MyForm ShowNew(Icon ico)
{
MyForm form = new MyForm(ico);
return form;
}
When instantiating
MyForm.ShowNew(Properties.Resources.my_icon);
Another approach would be implementing your form as usual, wrapping it in a Singleton-like class :
public static class WindowsFormSingleton {
// A static instance of your form
private static WindowsForm _form;
// A singleton property to interact with the form.
public static WindowsForm Instance
{
get
{
if(_form == null) {
this._form = new WindowsForm();
}
else if(_form.IsDisposed) {
this._form = new WindowsForm();
}
return this._form;
}
}
}
... and using the singleton instance like the following :
WindowsFormSingleton.Instance.Show();
Note: As taffer stated in the comments, using a Factory method to always create a new instance would be a better approach to this.
This question already has answers here:
Having two forms open and running a method on form1 from form2 [duplicate]
(2 answers)
Closed 7 years ago.
I want to call a function update in form1 on click even of button in form2. The update method will make changes to controls in form1. I am using this approach , but when I access it does not give access( when method is non static ) and when I make the method static it asks to make the controls static too which I don't want to. Is there any other way ?
public button1_click()
{
Form1.update();
}
// method in form1
public static void update()
{
control.Text="ab";
}
You can't access non-static variables in static methods. Refer to the documentation:
While an instance of a class contains a separate copy of all instance fields of the class, there is only one copy of each static field.
It is not possible to use this to reference static methods or property accessors.
In this case, if your update method (BTW should be Update) needs to access non-static members of your class, you should make it non-static, and change the Form2 as follows:
1) Add a field and change form's constructor to accept Form1 instance as a parameter:
private Form1 form1;
public Form2(Form1 form1)
{
this.form1 = form1;
}
2) When creating form2 from form1 pass its instance:
Form2 form2 = new Form2(this); // when in Form1
If you're creating Form2 in some other context you need to (analogically) have form1 instance at hand and call:
Form2 form2 = new Form2(form1);
3) Change the event handler to work on the particular instance of Form1:
public button1_click()
{
this.form1.update();
}
Why does my attempt at this fail?
I made this public on Form1.Designer.cs
public System.Windows.Forms.ProgressBar progressBar1;
and I can check it shares Form
public partial class Form3 : Form
and then tried this to update increment on another form "form3"
Form1.progressBar1.Increment(10);
I made this somewhat weird try because I saw simple "classname.variablename" for using data from another form working...
PS. If I am lucky enough to understand your generous answers... I think I will be able to bite off more of your further suggestions like "how about try inheritance" or "make instance for this"... :)
The problem with your attempt is that you are trying to access an instance member through the class name, rather than an actual instance reference.
When you create the Form3 instance, you need to pass it the reference to the Form1 instance, preferably via the constructor. E.g.:
partial class Form3 : Form
{
private readonly Form1 _form1;
public Form3(Form1 form1)
{
_form1 = form1;
}
}
Then you can access the ProgressBar instance like this:
_form1.progressBar1.Increment(10);
Note, however, that making the progressBar1 field public really isn't the right thing to do. It gives callers more access than they need, when your classes should be designed to give only the minimum access required.
It would be better to keep the field private and do something like this:
partial class Form1 : Form
{
public void IncrementProgress(int i)
{
progressBar1.Increment(i);
}
}
Then you'd access it like this :
_form1.IncrementProgress(10);
(still passing the Form1 instance to the constructor of Form3, of course).
Edit:
It's worth mentioning that I agree with the general sentiment expressed in the question comments that a better approach is for Form3 to expose some kind of progress event, and for Form1 to subscribe to that, rather than requiring Form3 to specifically know about the Form1 class at all.
The above code examples address the specific question, but if you are interested in a better design, it would look something like this:
partial class Form3 : Form
{
public event EventHandler IncrementProgress;
void SomeMethodWhereProgressHappens()
{
// ... make some progress
// Then raise the progress event
EventHandler handler = IncrementProgress;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
// ... then make some more progress, etc.
}
}
and in your Form1 class:
partial class Form1 : Form
{
void SomeMethodThatShowsForm3()
{
Form3 form3 = new Form3();
form3.IncrementProgress += (sender, e) => progressBar1.Increment(10);
form3.Show();
}
}
Note that in this approach, the Form3 class doesn't have any code at all that depends on the Form3 class specifically, and Form1 does not need to expose the ProgressBar instance in any way, not even via some proxy method.
Finally note that the reason an event is appropriate in this scenario is because of the callback nature of the operation. There are other scenarios where some caller, e.g. the code instantiating the class object itself, simply wants to set certain properties that map to control properties. In this case, the delegation/proxy approach I showed as the initial solution is still appropriate. It's a good technique to learn and use when it applies.
You need to create a public property on Form1:
public ProgressBar MyProgressBar
{
get
{
return progressBar1;
}
}
Then you can access it from Form3:
form1.MyProgressBar.Increment(10);
You'll probably need to create a property in Form3 also:
public Form MainForm
{
get; set;
}
So when you open Form3, you'll do this:
Form3 form3 = new Form3();
form3.Show();
form3.MainForm = this;
I need to call "panel.invalidate" outside my form (WINform) class also I need to change some other controls as well, I read similar question here, and tried what they said, but it didn't work and I wasn't convinced at all.
The answer I read was about exposing a public method like this:
public void EnableButton(bool enable)
{
this.myButton.Enabled = enable;
}
Also I made a static instance in the other file
static Form1 myForm = new Form1();
Any useful suggestions??
The problem is the "myForm" reference. It is a reference to an instance of Form1 that isn't visible and doesn't match the one that the user is looking at. It can't be a match, you created a new one.
Whatever class needs to update the form must have a constructor that takes a Form1 reference. You can create the class object in your Form1 constructor or Load event, pass "this". Using Application.OpenForms[0] is another way to get the reference, one you should not use.
Are you updating from the same thread? Otherwise you might need to use Invoke.
Here's a nice short article about how to do that:
http://blogs.msdn.com/csharpfaq/archive/2004/03/17/91685.aspx
Control.Invalidate() is a public method, but the control itself is most likely not public. You will have to expose the call to Control.Invalidate() through a public facing method in your form or by marking the control in question as public.
public class MyForm : Form {
private TextBox tbxName = new TextBox();
public InvalidateTextBox() {
tbxName.Invalidate();
}
}
OR
public class MyForm : Form {
public TextBox tbxName = new TextBox();
}
public class SomeOtherClass {
public void InvalidateTextBox(MyForm form) {
form.tbxName.Invalidate();
}
}