use Winform Objects inside an Static Method - c#

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.

Related

List going back to 0 after new form

I have this class:
public class Observador : iObservador
{
private List<Form> Forms = new List<Form>();
public void DeSubscribirse(Form form)
{
Forms.Remove(form);
}
public void Limpiar()
{
Forms.Clear();
}
public void Subscribirse(Form form)
{
Forms.Add(form);
}
public List<Form> DevolverSubscriptos()
{
return this.Forms;
}
}
Which is used on a base form I have like this:
public partial class FormBase : Form
{
public EE.Observador Watcher = new Observador();
public FormBase()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.Hide();
}
}
Which I use for the rest of my forms to be inherited from.
My idea is to have in all the forms a reference to the object Watcher from every place, with it having a reference for every form which is subscribed to it. So I can do for example, from FormB know that FormA is already subscribed with the method DevolverSubscriptos() (this means return subscribers) and access it to make it visible again after closing FormB.
The problem is that when I start FormB the list of Watcher with the whole forms is set back to 0.
What am I doing wrong? How can I solve it?
public partial class AdminUIGI : FormBase.FormBase
That's how I reference it.
Short answer: you're using an instance field. Each form is a separate instance, hence each has it's own copy of the EE.Observador.
So a quick and dirty fix would be to make this field static, i.e. shared by all instances of the given class. And if you want to improve, you might then consider reading about the Singleton pattern (mainly because you'll see it used a lot - but read on :) ), then read why using Singleton as a global variable is in fact an anti-pattern and move on to reading about dependency injection and IoC - which is how (in vacuum at least) your code should probably end up. (Note: for a quick and dirty solution static field is all you need).
#decPL I made it work with the singleton pattern doing this ` public sealed class Singleton
{
Singleton()
{
}
private static readonly object padlock = new object();
private static Singleton instance = null;
public static EE.Observador watcher = new Observador();
private Usuario userInstance = null;`

How to get access to a subclass when the other class only knows the superclass?

I have a C# Windows Forms Application form1.cs with a Class Library (DLL) called class1.cs. Now on the UI side I do the following:
using System;
...
using System.Windows.Forms;
using ClassLibrary1;
namespace UI
{
public partial class Form1 : Form
{
MyLibraryClass mlc = null;
public Form1()
{
InitializeComponent();
mlc = new MyLibraryClass(this);
}
public void aMethod() {
Console.Write("Test");
}
}
}
In the Class Library I take the Form reference and want to call the method within, but I don't have access to it:
...
using System.Windows.Forms;
namespace ClassLibrary1
{
public class MyLibraryClass
{
private Form _form;
public MyLibraryClass(Form form)
{
this._form = form;
this._form.aMethod(); //Not working!
}
}
}
The reason as I understand it is that my ClassLibrary1 only knows Form but not Form1 and hence cannot call methods from Form1. The problem is, the UI knows the Class Library but not the other way around, since that would create a ring dependency as you certainly know. But how can I solve this problem?
Instead depeding of Form you can create an interface.
public interface IMyInterface {
void aMethod();
}
Form1 will implement the interface we created
public partial class Form1 : Form, IMyInterface
{
MyLibraryClass mlc = null;
public Form1()
{
InitializeComponent();
mlc = new MyLibraryClass(this);
}
public void aMethod() {
Console.Write("Test");
}
}
In MyLibraryClass now you will depend on the interface not the form. This way MyLibraryClass can use any form that respect the contract and we make sure that in MyClassLibrary will never be passed any intruder form.
public class MyLibraryClass
{
private IMyInterface _form;
public MyLibraryClass(IMyInterface form)
{
this._form = form;
this._form.aMethod(); // now is work :)
}
}
Notes:
The interface will be created in Class Library project (where MyClassLibrary is created).
I recommend you to take a look on SOLID principles.
Circular dependencies are something you will want to avoid whenever possible, but let's assume you still need this.
The easiest solution would be to put the MyLibraryClass and Form1 in the namespace, so you can replace the Form type parameter with a Form1. If you want to keep things nicely separate however, you will have to add a new type.
In you library you would have to add an interface that contains that method.
public interface IMyInterface
{
void aMethod();
}
If you then change the parameter to an IMyInterface instead, you have access to that method. If you need access to normal Form methods or the aMethod is always the same, you could opt for an abstract class that inherits from Form too.
Depend upon Abstractions. Do not depend upon concretions
public interface IMethod
{
void aMethod();
}
public partial class Form1 : Form,IMethod
public MyLibraryClass(IMethod form)
{
this._form = form;
this._form.aMethod();
}
If you can, you should enforce statically the Form1 class in the argument list:
public MyLibraryClass(Form1 form)
{
// ...
}
If you cannot (which is often the case when several assemblies are used) you should test and cast dynamically:
public MyLibraryClass(Form form)
{
if (form is Form1)
{
(form as Form1).aMethod();
}
}
BUT YOU REALLY SHOULD honor the DIP (Dependency inversion principle), instead: depend from abstractions. Implement an interface and depend from that instead of Form1.
But if you've had the issue in the first place, you probably haven't cleared out for yourself how dependencies are organized between assemblies or, worse, don't know exactly why some answers propose to use interfaces.
Read the link above to know more about why, because your problem really is not about HOW but WHY.

C# Component Container

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!

Call panel.invalidate outside form class in C#

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();
}
}

shared functionality on usercontrol and form

I need to add shared functionality to both Forms and UserControls. Since multiple inheritance isn't supported in .net I wonder how I best tackle this?
The shared functionality is a dictionary that is filled by the form or usercontrol and then processed.
Regards
public class SharedFunctionality
{
public void ImportantToCallThisOnLoad();
}
public class MyForm : Form
{
SharedFunctionality mySharedFunctionality = new SharedFunctionality();
public void OnLoad()
{
mySharedFunctionality.ImportantToCallThisOnLoad();
}
}
public class MyControl : Control
{
SharedFunctionality mySharedFunctionality = new SharedFunctionality();
public void OnLoad()
{
mySharedFunctionality.ImportantToCallThisOnLoad();
}
}
Instead of having the Forms & UserControls inherit from a base class can you encapsulate the logic inside of a self contained object so that each form will new up? Then you can limit in the base class just the instantion and interaction with this object which hopefuly is minimal so having it done twice isn't a big deal.

Categories

Resources