Link to home
Start Free TrialLog in
Avatar of JpMaxMan
JpMaxManFlag for United States of America

asked on

Accessing Textbox from External Class

I'm sure this is a simple question and I'm overlooking the obvious.  But, I
have two seperate classes (in seperate files) under the same namespace.  I
am calling a method in one class that contains
public System.Windows.Forms.TextBox textBox1;

When I try to write to this textbox it never publishes anything.  If I call
the same method from inside the same class it does.  How can I publish to
this textbox from an external class.  Simple example would be:

FILE: classone.cs



namespace DemoApp

{

public class classone : System.Windows.Forms.Form

{

public System.Windows.Forms.TextBox textBox1;

private System.ComponentModel.Container components = null;

public classone()

{

InitializeComponent();

}

private void InitializeComponent()

{



this.textBox1 = new System.Windows.Forms.TextBox();

((System.ComponentModel.ISupportInitialize)(this.timer1)).BeginInit();

//

// textBox1

//

this.textBox1.Location = new System.Drawing.Point(0, 32);

this.textBox1.Multiline = true;

this.textBox1.Name = "textBox1";

this.textBox1.ReadOnly = true;

this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Both;

this.textBox1.Size = new System.Drawing.Size(568, 344);

this.textBox1.TabIndex = 4;

this.textBox1.Text = "textBox1";

//

// classone

//

this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

this.ClientSize = new System.Drawing.Size(568, 373);

this.Controls.Add(this.textBox1);



this.Load += new System.EventHandler(this.Form1_Load);

((System.ComponentModel.ISupportInitialize)(this.timer1)).EndInit();

this.ResumeLayout(false);

}

public void addstatus(string status)

{

MessageBox.Show(status);

this.textBox1.AppendText("HI");

this.textBox1.AppendText(status + "\r\n\r\n");


}

}

}

FILE classtwo.cs

namespace DemoApp

{

public void addToreport(string rep, int debugDetail)

{

classone obj = new classone();

obj.addstatus(rep);

}

}



When calling the addToreport method, everything compiles and runs - just
nothing gets written to the textbox window.  Not even the "HI" - the
information does show correctly in the MessageBox.
Avatar of Wim_Bl
Wim_Bl
Flag of Belgium image

Hi,

I found this line of code in your code:

this.textBox1.ReadOnly = true;

couldn't that be the problem ?

greetings!
Avatar of JpMaxMan

ASKER

No, that just refers to the ability for the user to enter/modify text in the textbox.  

Keep in mind that this all works as I'd like it to if everything is in the same class.  It's when I attempt to populate this textbox from a seperate class that I'm running into problems.
As some additional information I tried this:

      public string ValueForTextBox
            {
                  set
                  {
                        this.textBox1.text += value;
                  }
                  get
                  {
                        return this.textBox1.Text;
                  }

and I get a bit more informative error:

'System.Windows.Forms.Control.text' is inaccessible due to its protection
level

However, I thought I had this as public by using:

            public System.Windows.Forms.TextBox textBox1;


So, how do I set the protection level so that I can write to this textbox?
Can you re post your entire source for all CS files?

FILE ONE seemed to be missing some stuff
Sure - created a new project to demonstrate this:

file FORM1.CS

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace simpleapp
{
      /// <summary>
      /// Summary description for Form1.
      /// </summary>
      public class Form1 : System.Windows.Forms.Form
      {
            private System.Windows.Forms.TextBox textBox1;
            private System.Windows.Forms.Button button1;
            /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.Container components = null;

            public Form1()
            {
                  //
                  // Required for Windows Form Designer support
                  //
                  InitializeComponent();

                  //
                  // TODO: Add any constructor code after InitializeComponent call
                  //

            }


            public void addstatus(string status)
            {
                  
                  this.textBox1.AppendText(status + "\r\n\r\n");
            }

            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            protected override void Dispose( bool disposing )
            {
                  if( disposing )
                  {
                        if (components != null)
                        {
                              components.Dispose();
                        }
                  }
                  base.Dispose( disposing );
            }

            #region Windows Form Designer generated code
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                  this.textBox1 = new System.Windows.Forms.TextBox();
                  this.button1 = new System.Windows.Forms.Button();
                  this.SuspendLayout();
                  //
                  // textBox1
                  //
                  this.textBox1.Location = new System.Drawing.Point(0, 24);
                  this.textBox1.Multiline = true;
                  this.textBox1.Name = "textBox1";
                  this.textBox1.ReadOnly = true;
                  this.textBox1.Size = new System.Drawing.Size(296, 240);
                  this.textBox1.TabIndex = 0;
                  this.textBox1.Text = "";
                  //
                  // button1
                  //
                  this.button1.Location = new System.Drawing.Point(0, 0);
                  this.button1.Name = "button1";
                  this.button1.Size = new System.Drawing.Size(296, 23);
                  this.button1.TabIndex = 1;
                  this.button1.Text = "button1";
                  this.button1.Click += new System.EventHandler(this.button1_Click);
                  //
                  // Form1
                  //
                  this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
                  this.ClientSize = new System.Drawing.Size(292, 266);
                  this.Controls.Add(this.button1);
                  this.Controls.Add(this.textBox1);
                  this.Name = "Form1";
                  this.Text = "Form1";
                  this.ResumeLayout(false);

            }
            #endregion

            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                  Application.Run(new Form1());
            }

            private void button1_Click(object sender, System.EventArgs e)
            {
                  addstatus("Part one, I work \r\n\r\n");

                  Class1 cls1 = new Class1();
                  cls1.addstatustoo("Part three, I don't work \r\n\r\n");
            }
      }
}


FILE CLASS1.CS:

using System;

namespace simpleapp
{
      /// <summary>
      /// Summary description for Class1.
      /// </summary>
      public class Class1
      {
            public Class1()
            {
                  //
                  // TODO: Add constructor logic here
                  //
                  
                  addstatustoo("part two, I don't work \r\n\r\n");
                  


            }

            public void addstatustoo(string status)
            {
                  //this doesn't work.
                  Form1 obj = new Form1();
                  obj.addstatus("hi");
            }
      }
}
I played around with this a little bit.....try this:




Create a NEW Windows Application and accompanying Class file:



Form Source:


using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace simpleapp
{
      /// <summary>
      /// Summary description for Form1.
      /// </summary>
      public class FormTest : System.Windows.Forms.Form
      {
            private System.Windows.Forms.TextBox textBox1;
            private System.Windows.Forms.Button button1;
            /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.Container components = null;

            public FormTest()
            {
                  //
                  // Required for Windows Form Designer support
                  //
                  InitializeComponent();

                  //
                  // TODO: Add any constructor code after InitializeComponent call
                  //

            }


            public void addstatus(string status)
            {
               
                  this.textBox1.AppendText(status + "\r\n\r\n");
            }

            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            protected override void Dispose( bool disposing )
            {
                  if( disposing )
                  {
                        if (components != null)
                        {
                              components.Dispose();
                        }
                  }
                  base.Dispose( disposing );
            }

            #region Windows Form Designer generated code
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                  this.textBox1 = new System.Windows.Forms.TextBox();
                  this.button1 = new System.Windows.Forms.Button();
                  this.SuspendLayout();
                  //
                  // textBox1
                  //
                  this.textBox1.Location = new System.Drawing.Point(0, 24);
                  this.textBox1.Multiline = true;
                  this.textBox1.Name = "textBox1";
                  this.textBox1.ReadOnly = true;
                  this.textBox1.Size = new System.Drawing.Size(296, 240);
                  this.textBox1.TabIndex = 0;
                  this.textBox1.Text = "";
                  //
                  // button1
                  //
                  this.button1.Location = new System.Drawing.Point(0, 0);
                  this.button1.Name = "button1";
                  this.button1.Size = new System.Drawing.Size(296, 23);
                  this.button1.TabIndex = 1;
                  this.button1.Text = "button1";
                  this.button1.Click += new System.EventHandler(this.button1_Click);
                  //
                  // Form1
                  //
                  this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
                  this.ClientSize = new System.Drawing.Size(292, 266);
                  this.Controls.Add(this.button1);
                  this.Controls.Add(this.textBox1);
                  this.Name = "FormTest";
                  this.Text = "FormTest";
                  this.ResumeLayout(false);

            }
            #endregion

            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                  Application.Run(new FormTest());
            }

            private void button1_Click(object sender, System.EventArgs e)
            {
                  addstatus("Part one, I work \r\n\r\n");

                  Class1 cls1 = new Class1(this);
                  cls1.addstatustoo("Part three, I don't work \r\n\r\n");
            }
      }
}











Class Source:



using System;

namespace simpleapp
{
      /// <summary>
      /// Summary description for Class1.
      /// </summary>
      public class Class1
      {
            public FormTest frmInClass = new FormTest();

            public Class1(FormTest frm)
            {
                  //
                  // TODO: Add constructor logic here
                  //

                  frmInClass = frm;
               
                  //addstatustoo("part two, I don't work \r\n\r\n");
               


            }

            public void addstatustoo(string status)
            {
                  //this doesn't work.
//                  Form1 obj = new Form1();
//                  obj.addstatus("hi");
//                  Form1.ActiveForm.Refresh();

                  frmInClass.addstatus("hi");
                  frmInClass.Refresh();
            }
      }
}
Ok  - so you are passing the form when you instantiate the class.  Got that.  But, for my purposes this won't work.   What I am trying to accomplish is I have a windows service that I sometimes compile as a windows form application for debugging purposes.  I'm trying to use the same classes then have the constructors be slightly different on two seperate projects.  If I compile one it builds the service.  If I compile other it builds the form.  

What I am attempting to do seems like it should be simple. I am trying to create a method ( addstatus) that would be in the constructor for both the form and the service which I can call from the class files to log information.   In the case of the form - it would spit this out to the textbox.  In the case of hte service it's going to a file.

So, the solution to pass the form when instantiating hte class won't work for me.   Is there another way ?
Hmmmmm.....

Not sure how to answer your question...given your clarification.

I will think on this some...if anything comes to me I'll let you know.

Tom
Let me see if I have this straight.


You have a Windows Service, let's say WSClass is the class.


If you instantiate WSClass("DebugAsForm") (for example) it compiles as a Form which you can debug.

If you instantiate WSClass("WS") (for example) it compiles as a Windows Service which you install and start?

Have I got it right?
No, you're overthinking it... much simpler.   I have two seperate projects.  One project is a Windows Form.  The other is a Windows Service.  Each one simply calls the same class - call it Class1.   I have a metod which gets called to report debugging info.  In my Windows Service project this method writes the string to a file (works fine).  In my Windows Form project the method is trying to write the string to the textbox.  Does not work.
Incidentally, I can have it report the info in MessageBox's:

MessageBox.Show(status)

and it works fine.  It just won't put it into the textbox - it seems to be some level of protection that prevents this, but I'm not clear on what/where.
So you are saying....if I can tweak the example I gave you so it does the same thing...but does NOT pass in the Form object to the constructor..then you would be okay?
You cannot overload the Constructor for Class1 like this:


Class1 c1 = new Class1( )   //  no parameter constructor for Windows Service

Class c1 = new Class1(this)  //  1 parameter constructor for Windows Form

?????

Sorry for being so dense...just trying to help.  :)
Most likely.  The other approach that I looked at was to use a static method in the Form1 class:

            public static void addstatus(string status)
            {
                  Form1 obj = new Form1();
                  obj.textBox1.AppendText(status + "\r\n\r\n");
                  
            }

Then from class1 I could simply call:

Form1.addstatus("text I want written in the textbox);

Though this is the same result.  I feel like there is relaly something simple here that is not being done.
Yeah, I thought about doing an overload, but once again the point is to streamline it - if I was going to do an overload I could also maintain seperate class files :) (one for the service, one for the form)
I know that in the past I have used Delegates to solve problems like this.....I'll have to see if I can find the code....
>>>>Yeah, I thought about doing an overload, but once again the point is to streamline it - if I was going to do an overload I could also maintain seperate class files :) (one for the service, one for the form)


Point taken.  :)


The whole point is to have ONE constructor call that handles both....right?



Right - from both my Windows Form project and my Windows Service project, I would simply call:

Class1 workerclass = new Class1();
workerclass.workermethod();

The more I think about this, a static method may be the way to go, so in my service I woud have:

public static void addstatus (string status)
{
//Write status to file
}

and in my Windows Form I would have:

public static void addstatus (string status)
{
//Write status to textbox of form
}

Make sense?
Just thinking out loud.....

What about passing one parameter to the Class1 constructor.....whethe it is a Windows Service or a Windows Form:

public Class1
{
   public Class1(object SourceObject)
  {
        if(SourceObject is WindowsService)
        {
            //  do what you are doing that works
        }
        else
        {
             //  it is a form....cast the SourceObject   as   Form1    and display text to TextBox control on Form1
        }
  }
}
The more I think about this, a static method may be the way to go, so in my service I woud have:

public static void addstatus (string status)
{
//Write status to file
}

and in my Windows Form I would have:

public static void addstatus (string status)
{
//Write status to textbox of form
}



If these methods are going into your Windows Service code and your Windows Form code respectively........then why have the Class1   at all???????
>>If these methods are going into your Windows Service code and your Windows Form code respectively........then why have the Class1   at all???????

Because in my actual project, my class1 has a ton of methods and I want to be able to chagne one class file - if I compile that class file into my Windows Form it runs as a windows form application and if I compile class1 into my service it runs as a service.  

I just can't believe that it is so difficult to just call a static method in a different class passing a string and have it display in a textbox.
You are saying that your static method idea does NOT work??????

Seems like it should work just fine!!!!


So this is when you run into the protection level crap??
Try this:


CLASS CODE:


using System;

namespace simpleapp
{
      public class Class1
      {
            public Class1()
            {
            }

            public void addstatustoo(string status)
            {
                  FormTest.addstatus(status);
            }
      }
}









FORM CODE:


using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace simpleapp
{
      /// <summary>
      /// Summary description for Form1.
      /// </summary>
      public class FormTest : System.Windows.Forms.Form
      {
            private static System.Windows.Forms.TextBox textBox1;
            private System.Windows.Forms.Button button1;
            /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.Container components = null;

            public FormTest()
            {
                  //
                  // Required for Windows Form Designer support
                  //
                  InitializeComponent();

                  //
                  // TODO: Add any constructor code after InitializeComponent call
                  //

            }


            

            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            protected override void Dispose( bool disposing )
            {
                  if( disposing )
                  {
                        if (components != null)
                        {
                              components.Dispose();
                        }
                  }
                  base.Dispose( disposing );
            }

            #region Windows Form Designer generated code
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                  FormTest.textBox1 = new System.Windows.Forms.TextBox();
                  this.button1 = new System.Windows.Forms.Button();
                  this.SuspendLayout();
                  //
                  // textBox1
                  //
                  FormTest.textBox1.Location = new System.Drawing.Point(0, 24);
                  FormTest.textBox1.Multiline = true;
                  FormTest.textBox1.Name = "textBox1";
                  FormTest.textBox1.ReadOnly = true;
                  FormTest.textBox1.Size = new System.Drawing.Size(296, 240);
                  FormTest.textBox1.TabIndex = 0;
                  FormTest.textBox1.Text = "";
                  //
                  // button1
                  //
                  this.button1.Location = new System.Drawing.Point(0, 0);
                  this.button1.Name = "button1";
                  this.button1.Size = new System.Drawing.Size(296, 23);
                  this.button1.TabIndex = 1;
                  this.button1.Text = "button1";
                  this.button1.Click += new System.EventHandler(this.button1_Click);
                  //
                  // Form1
                  //
                  this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
                  this.ClientSize = new System.Drawing.Size(292, 266);
                  this.Controls.Add(this.button1);
                  this.Controls.Add(FormTest.textBox1);
                  this.Name = "FormTest";
                  this.Text = "FormTest";
                  this.ResumeLayout(false);

            }
            #endregion

            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                  Application.Run(new FormTest());
            }

            private void button1_Click(object sender, System.EventArgs e)
            {
                  addstatus("Part one, I work \r\n\r\n");

                  Class1 cls1 = new Class1();
                  cls1.addstatustoo("Part three, I don't work \r\n\r\n");
            }

            public static void addstatus(string status)
            {            
                  textBox1.AppendText(status + "\r\n\r\n");
            }
      }
}
ASKER CERTIFIED SOLUTION
Avatar of Tom Knowlton
Tom Knowlton
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Errr...I guess FormTest is not static....
This may be even closer to what you had in mind.  Now the constructor does the work...no need to call a seperate Class1 method anymore:


using System;

namespace simpleapp
{
      public class Class1
      {
            public Class1()
            {
                  FormTest.addstatus("Some new message you need to see");
            }
      }
}
Right you are! Though, I'd love an explanation if anyone cares to give one about why the textbox wouldn't work when it's instantiated??
Dunno.