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();
}
}
Related
I have a problem that I could ignore a long time but now I have to solve it.
I have 3 GUI (Winform) 1 Main 1 Settings and 1 for a Webbrowser.
I need to call a Method that is in my Webbrowser Form inside my Main Form for that reason the Method is a static one.
But if I set it to static it giveĀ“s me an error if I try to work with the Objects from the Form.
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
public static void WebLyrics(string url){
webBrowser1.Navigate(url);
}
}
The easiest way is to:
Add a static Instance property to the webbrowser form:
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
Instance = this;
}
public static Form3 Instance { get; private set; }
public void WebLyrics(string url)
{
webBrowser1.Navigate(url);
}
}
and call the WebLyrics method via the Instance property in the other form:
public partian class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Navigate()
{
Form3.Instance.WebLyrics("www.stackoverflow.com");
}
}
I assumed you create both forms somewhere somehow...
You should consider changing the code. Why is your Form having a static method? It doesn't make any sense. The easiest way to achieve it is to pass reference to the Webbrowser Form into the Main Form. Or you can instantiate the Webbrowser form inside you Main Form and then show it.
But I suggest that you introduce a way of separating the UI from the business logic layer. Consider to introduce MVC / MVP pattern, to have a clear separation, and then the forms do not need to have references to each other directly.
The easiest (= least code) way to solve it is probably to use singletons for the forms as other have suggested, or even simpler to use the built in forms registry:
var myForm3 = Application.OpenForms.OfType<Form3>.FirstOrDefault();
I would probably prefer to use a separate singleton for holding the forms, as I would find it more maintainable. This would be a better separation of concerns in that the forms would not have to be created as singletons and could be reused in other ways. It is truly your app's UI layout that is the singleton.
Something like this:
public class AppLayout
{
public static AppLayout Instance {
get { ... }
}
public WebBrowserForm WebBrowser {get;private set;}
public MainForm Main {get;private set;}
public SettingsForm Settings {get;private set;}
}
Think of it like a typed variant of the Application singleton.
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 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.
I am developing a C# windows form application and on the main form I have a TabControl. It is declared in the Form1.Designer.cs file as follows:
public System.Windows.Forms.TabControl logFileCollectorTabControl;
In another class file in my project I want to use this TabControl as follows:
logFileCollectorForm.logFileCollectorTabControl.TabPages.Add(newTabPage);
But I get the error 'An object reference is required for the non-static field, method or property error'. So my question is, there must be an object of the Form class declared somewhere because the form launches when I launch the application, so how do I find out what that is, or how can I solve this issue, any help is greatly appreciated!
This is usually overcome by passing in an instance of Form1 to the constructor of the calling class, then keeping it in a field until needed.
//somewhere in Form1
OtherClass other = new OtherClass (this);
// OtherClass.cs
class OtherClass {
Form1 _opener;
public OtherClass(Form1 opener) {
_opener = opener;
}
}
Is your other class aware of logFileCollectorForm?
If you do not pass a reference to the form to the other class, then the other class does not know what Is logFileCollectorForm is referencing.
//example of another class
class AnotherClass
{
Form1 logFileCollectorForm;
public AnotherClass(Form1 logFileCollectorForm)
{
this.logFileCollectorForm = logFileCollectorForm;
}
public DoSomething(String newTabPage)
{
logFileCollectorForm.logFileCollectorTabControl.TabPages.Add(newTabPage);
}
}
There is probably no need to pass an instance of an entire form, you could pass a reference to your TabControl only. But it's still bad design in my opinion. Your logic should be separated from UI. If your class performs some computations, database operations or what not, it shouldn't really have to "know" about your window at all, because this is inflexible. Implement an event instead.
Another option is to keep a static reference to the main form in the Program class.
static class Program
{
internal static Form1 MainForm { get; set; }
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MainForm = new Form1();
Application.Run(MainForm);
}
}
class OtherClass
{
public void AddNewTab(TabPage newTabPage)
{
Program.MainForm.logFileCollectorTabControl.TabPages.Add(newTabPage);
}
}
I have a windows form and my own class in my project
I have a method in my own class
public object Sample(Form MyForm,string ComponentName)
{
}
I want to get components of the "MyForm" from another class How Can I Make THIs?
form class
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
MyOwnClass
public class Sample
{
public object GetComponentMethod(Form form,string ComponentName)
{
////
}
}
Have you tried with:
Control myControl= form.controls.Find(...)?
updated
Sorry but in this case I cannot understand what are you looking for!
updated
you have to create a public property Components! So you can retrieve data you need!
It looks like you are just trying to access members of one object from another object.
If so you need to expose some way of accessing a specific instance of a class.
If you will only ever have one instance (of say your Form1) the simplest way is to expose that single instance via a public static property. This is called a singleton pattern:
public partial class Form1 : Form
{
public static Form1 Singleton { get; private set; }
public Form1()
{
Form1.Singleton = this;
InitializeComponent();
}
}
You can the access your Form1 instance using Form1.Singleton.SomeProperty from anywhere.
I am not promoting any specific Singleton pattern here, as there are too many issues over thread safety, but for your simple example this will do the job. Call the static property "Singleton" or "This" or "SolutionToMyWoes" or whatever you like!