19

I have a windows forms application with some controls added to the designer. When I want to change something (LIKE) enabling a text box from inside the Form1.cs, I simply use:

textBox1.Enabled = true;

but now I have a separated class called class1.cs.

How could I enable textBox1 from a static function class1.cs?

NOTE: I did not try any code because I am totally clueless about doing this.

Oriol Roma
  • 329
  • 1
  • 5
  • 9
Roman Ratskey
  • 5,101
  • 8
  • 44
  • 67
  • 1
    for what reason u want to do that? I think you should change your design – Sleiman Jneidi Oct 19 '12 at 22:44
  • change my design !. it is the nature of windows forms that i can't access the controls from outside the Form1.cs because they are private. – Roman Ratskey Oct 19 '12 at 22:48
  • 1
    Have you tried to pass a reference to the Control in your class? It could be an argument of a static method. You need to give the context of the class1.cs. Is it derived control, where do you hold instances of it etc. – Nikola Davidovic Oct 19 '12 at 22:56

12 Answers12

24

EDIT: Lot of edit.

public partial class Form1 : Form
{
    // Static form. Null if no form created yet.
    private static Form1 form = null;

    private delegate void EnableDelegate(bool enable);

    public Form1()
    {
        InitializeComponent();
        form = this;
    }

    // Static method, call the non-static version if the form exist.
    public static void EnableStaticTextBox(bool enable)
    {
        if (form != null)
            form.EnableTextBox(enable);
    }

    private void EnableTextBox(bool enable)
    {
        // If this returns true, it means it was called from an external thread.
        if (InvokeRequired)
        {
            // Create a delegate of this method and let the form run it.
            this.Invoke(new EnableDelegate(EnableTextBox), new object[] { enable });
            return; // Important
        }

        // Set textBox
        textBox1.Enabled = enable;
    }
}
LightStriker
  • 19,738
  • 3
  • 23
  • 27
  • And you need to have a reference of your form that contains the textBox you are trying to Enable/Disable – Nikola Davidovic Oct 19 '12 at 22:47
  • then an instance from the Form class should be created, is this a good idea? – Sleiman Jneidi Oct 19 '12 at 22:47
  • @Nick: Sorry... But that's a bit obvious, or am I missing something? If you want to edit something inside an object, you have to have created and referenced that object in the first place. – LightStriker Oct 19 '12 at 22:49
  • i want to know how to access the control from static functions too – Roman Ratskey Oct 19 '12 at 22:49
  • @Marc-AndréJutras OK, but say that to the guy that posted the question. Few minutes ago there was a similar question that was closed. – Nikola Davidovic Oct 19 '12 at 22:50
  • Nick could you just help me as long as you can i really wanna some clear help about this. also i don't know which question are you talking about but let's back to the topic – Roman Ratskey Oct 19 '12 at 22:55
  • I have to wonder though, why static? Why not access the setter from the instance? – System Down Oct 19 '12 at 22:56
  • @System Down: The hell I know. I wouldn't do that... But that was the question. Talk of weird design. – LightStriker Oct 19 '12 at 22:57
  • guys don't act as i am that professional in programming as you are. so i want to learn from you if you were creating a windows forms application what would you do the access the controls in the main Form from another classes and\or instances ? – Roman Ratskey Oct 19 '12 at 23:00
  • @Torlan: I wouldn't do static because it limits future change to only have a single instance of your form at all time. Static basicly means that, a single instance. You can have a list of existing forms contained at the root of your application and get it from there and use a basic accessor instead. In one of my app, I have a collection of dockable panel I can access from everywhere at all time. So if I have 5 forms of type X, I can get them all at once and call methods in them. – LightStriker Oct 19 '12 at 23:04
  • But in general, you should let the form manage its own content. If you want to trigger an action from outside, you should do it by a method or an event and let the form handle it. The idea of letting anybody outside handling inner form controls at all time can lead to some very bad problems. – LightStriker Oct 19 '12 at 23:07
  • but i always get that error Invoke or BeginInvoke cannot be called on a control until the window handle has been created. – Roman Ratskey Oct 19 '12 at 23:13
  • @Torlan: That's one of the reason why a UI item is never controlled directly from an external class. UI Element really are single-threaded and hate deeply being call from a thread not native to the form. – LightStriker Oct 19 '12 at 23:16
  • and that i want to get around... i just want to be able to update my guid from the classes that are doing some functions so for instance if i have a class that calculates 100+100 when getting the result it updates the textbox.Text to that result. – Roman Ratskey Oct 19 '12 at 23:18
  • Now we are getting toward something. The idea is to let the form handle its own stuff. I re-edit my answer. – LightStriker Oct 19 '12 at 23:27
18

This is just another method:

TextBox t = Application.OpenForms["Form1"].Controls["textBox1"] as TextBox;
vr_driver
  • 1,867
  • 28
  • 39
5

You shouldn't really change UI controls in your Form from your class1, but instead create a method or a property in class1 that would tell if the textbox should be enabled or not.

Example:

// I changed the name class1 to MySettings
public class MySettings
{
    public bool ShouldTextBoxBeEnabled()
    {
        // Do some logic here.
        return true;
    }

    // More generic
    public static bool SetTextBoxState(TextBox textBox)
    {
        // Do some logic here.
        textBox.Enabled = true;
    }

    // Or static property (method if you like)
    public static StaticShouldTextBoxBeEnabled { get { return true; } }
}

Then in your form:

MySettings settings = new MySettings();
textBox1.Enabled = settings.ShouldTextBoxBeEnabled();

// Or static way
textBox1.Enabled = MySettings.StaticShouldTextBoxBeEnabled;

// Or this way you can send in all textboxes you want to do the logic on.
MySettings.SetTextBoxState(textBox1);
Mario S
  • 11,715
  • 24
  • 39
  • 47
4

You can pass the instance of your Form to the class

 MyForm frm = new MyForm();

 MyClass c = new MyClass(frm);

Then your class can take that instance and access the textbox

 public class MyClass
 {

   public MyClass(MyForm f)
   {
      f.TextBox1.Enabled = false;
   }
 }

The design does not look OK

It is better to call the class in your form and based on the value returned, manipulate the textbox

//MyForm Class

 MyClass c = new MyClass();
 c.DoSomethings();
 if(c.getResult() == requiredValue)
   textBox1.enabled = true;
 else
   textBox1.enabled = false;

//MyForm Class ends here

UPDATE

public class Class1
{
   public static int SomeFunction()
   {
      int result = 1;
      return result;
   }

   public static void SomeFunction(out int result)
   {
      result = 1;
   }
}

Usage

if(Class1.SomeFunction() == 1)
   textBox1.Enabled = true;
else
   textBox1.Enabled = false;

OR

int result = 0;
Class1.SomeFunction(out result);

if(result == 1)
   textBox1.Enabled = true;
else
   textBox1.Enabled = false;
codingbiz
  • 26,179
  • 8
  • 59
  • 96
3

You could let your class1 have an event to enable the Textbox.

public class Class1
{
  public event Action<object, EventArgs> subscribe ;
  private void raiseEvent()
  {
     var handler = subscribe ;
     if(handler!=null)
     {
        handler(this,EventArgs.Empty);//Raise the enable event.
     }
  }
}

Let the class containing the TextBox subscribe to it somehow. In TextBox wrapper class

 public class TextBoxWrapper
       public void EnablePropertyNotification(object sender, EventArgs args) 
       {
          TextBox1.Enabled = true ; //Enables textbox when event is raised.
       }
       public TextBoxWrapper()
       {
         class1Instance.subscribe+=EnablePropertyNotification ;
       }
Lews Therin
  • 10,907
  • 4
  • 48
  • 72
  • How could i enable textBox1 from a static function class1.cs ? – Roman Ratskey Oct 19 '12 at 22:53
  • I would ask why it was a static method. If you give me a good reason as to why then I'd think about it – Lews Therin Oct 19 '12 at 22:55
  • The good reason is that i have built all my Asynchronous Socket as an static one so i can't just replace all again. also another good reason is that i want to learn both ways. – Roman Ratskey Oct 19 '12 at 22:57
  • @TorlanOther - So keep a static reference to the form. Reason why everyone is harping on about this, is that using static is usually seen as bad design unless you have a really really good reason. – System Down Oct 19 '12 at 23:01
3

To access/modify a Form Element property, just write this in your outside Class.

Form1.ActiveForm.Controls["textBox1"].Enabled = true;

Where textBox1 is the variable name of TextBox.

What this actually does: Gets the active Form object's control specified by the name in string.

WARNING: Active form means the form which is currently open and focused on. If you do something else on your computer, with your minimized WindowsForm application, the Form1.ActiveForm will not get the form, instead, it will give null, which can lead to errors later. Be careful!

Ali Sajjad
  • 3,589
  • 1
  • 28
  • 38
2

based on the answer from @vr_driver you can do that to avoid problems with other containers like groupbox, panels...

TextBox t = Application.OpenForms["Form1"].Controls.Find("textBox1", true)[0] as TextBox;
  • Literally the only thing that worked for being new to creating classes. Thank you for this. – WLFree Sep 30 '22 at 03:48
1

In this example you have a form called Main.cs and a class called MyClass:

In MyClass (Note: the name of my Form Class = 'Main'):

Main ui = new Main();
ui.toolStripProgressBarStickers.PerformStep();

In (FormName).Designer.cs so in my case Main.designer.cs change the appropriate control from 'private' to 'public':

public System.Windows.Forms.ToolStripProgressBar toolStripProgressBarStickers;

This solved it for me. Thanks, Ensai Tankado

Dikkie Dik
  • 31
  • 2
0

I had to do this at work and didn't find that any of these answers matched what I ended up doing, so I'm showing how I made it work.

First, initialize a copy of your class in your load event.

NameOfClass newNameofClass;

Then you want to bind to your class (in the load event):

textBox1.DataBindings.Add(new Binding("Enabled", newNameofClass, "textBox1Enabled"));

In your class, do the following:

private bool textBox1Enabled = false;
public bool TextBox1Enabled
{
    get
        {
            return textBox1Enabled;
        }
        set
        {
            textBox1Enabled = value;
        }
}
  • The false setting will initialize your textbox to being disabled
  • Set textBox1Enabled to true if you want to enable by default.
  • If you have other logic to enable/disable the textbox, simply modify the value of textBox1Enabled accordingly.
noel
  • 383
  • 4
  • 18
0

Very easy:

Create an Instance of your Form Object where want to access the Elements from.

Form1 ui = new Form1();

and now change the Form Elements to "public" - like this in the Designer Code:

...
public System.Windows.Forms.TextBox textBox6;
...

Now you can access them like this in your Code:

ui.textBox6 ...
Dharman
  • 30,962
  • 25
  • 85
  • 135
Ensai Tankado
  • 189
  • 1
  • 4
0

I had the same problem. I used windows forms & Visual Studio to generate a UI in a utility with textbox, checkbox, and button controls but ALL the code was in the same class.

I'm rewriting the utility now that I know "more" OOP concepts and created actual objects and separate classes. I too had problems getting the separate classes to be able to access the form controls and any shared methods that are in the form class. I tried the various suggestions in this thread as well as other threads but none of those solutions worked for me.

What worked for me (not sure if its the right thing to do or not) was I had each class that needed to access the controls and forms methods inherit from the Form. Here is the relevant part of the Form.cs file:

namespace Utility
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        public void WriteNote(string noteText, bool asHeading = false)
        {
            //Writes Messages to the Message box in the UI
            Font font1 = new Font(this.ResultsTB.Font, FontStyle.Bold);
            Font font2 = new Font(this.ResultsTB.Font, FontStyle.Regular);
            if (asHeading)
                this.ResultsTB.Font = font1;
            else
                this.ResultsTB.Font = font2;
            this.ResultsTB.AppendText(noteText + "\r\n");
        }

My Form contains a textbox called DirTB and a method called "WriteNote" that writes info to another textbox called ResultsTB. Here is the class (at least as far down as the first successful call of the WriteNote method from the Form:

namespace Utility
{
    public class AppServerDTO : Form1
    {
        #region App Server attributes
//attributes listed here
        #endregion App Server attributes

        #region AppServerDTO Constructor
        public AppServerDTO()
        {
            //These methods verify and set all the attributes
            VerifyInstallFolder();
        }//end of constructor AppServer
        #endregion AppServerDTO Constructor

        #region AppServerDTO class methods 

        public void VerifyInstallFolder()
        {
            string keypath = string.Empty;
            string locationVerification = DirTB.Text + @"\SomeText";
            for (int i = 0; i < 4; i++) //allows 3 attempts to get the install folder right
            {
                if (Directory.Exists(locationVerification))
                {
                    i = 4;//Kills the loop
                }
                else if (!Directory.Exists(locationVerification))
                {
                    locationVerification = DirTB.Text + @"\SomeMoreText";
                }
                else if (!Directory.Exists(locationVerification))
                {
                    WriteNote("The directory listed in the Install Directoy box is not reachable.");
                    WriteNote("Please select the correct directory.");
                    WriteNote("The correct directory is the folder that contains the ApplicationUpdates & UpdateManager folders.");
                    WriteNote(@"i.e. C:\Somewhere or D:\Someplace\Somewhere");
                    var folderpath = FolderPrompt(@"C:\");
                    DirTB.Text = folderpath; //updates the install folder textbox to the new location
                    keypath = folderpath;
                    i++;
                }
            }//end for loop

        }//end VerifyInstallFolder

As long as you are very careful with what you mark as public vs private, it should be ok.

MariaNex
  • 3
  • 1
  • 4
-1

This is how you should do : I wrote the code below in my form class :

public static Form1 form = null;

    private delegate void SetImageDelegate(Image image);

    public Form1()
    {
        InitializeComponent();
        form = this;
    }

    public static void SetStaticImage(Image image)
    {
        if (form != null)
            form.pic1.Image = image;
    }

    private void setImage(Image img)
    {
        // If this returns true, it means it was called from an external thread.
        if (InvokeRequired)
        {
            // Create a delegate of this method and let the form run it.
            this.Invoke(new SetImageDelegate(setImage), new object[] { img });
            return; // Important
        }

        // Set textBox
        pic1.Image = img;
    }

and the code below should be in anouther class :

Form1 frm= Form1.form;
frm.pic1.Image = image;

Note that i changed private static Form1 form = null; to public static Form1 form = null;

Good Luck ... Written by Hassan Eskandari :)