Accesing C# Form textbox from another class file

2020-05-03 06:26发布

问题:

I want to access Form1 elements from another class file (chartscopier.cs for example), but I can't change textbox1 text from chartscopier.cs.

How can I do this?

Here is my code:

Form1.cs

namespace TEST
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            var CopyCharts = new System.Threading.Timer(chartscopier.CopyGraph, null, 0, 60000);
        }
    }
}

chartscopier.cs

namespace TEST
{
    class chartscopier
    {
        //var Timer = new Timer(CopyGraph, null, 0, 60000);
        public static void CopyGraph(object data)
        {
            Stopwatch strTimer = new Stopwatch();
            WebClient WC = new WebClient();
            IConfigSource BaseConfig = new IniConfigSource(@"D:\NEWROBOT\CONFIG.ini");
            string LogDir = BaseConfig.Configs["GENERAL"].Get("Log Dir");
            string ImgDir = BaseConfig.Configs["GENERAL"].Get("IMG Dir");
            string[] Clients = BaseConfig.Configs["CLIENTS"].GetKeys();
            foreach (string Client in Clients)
            {
                strTimer.Start();
                //Console.WriteLine(Client);
                IConfigSource ClientConfig = new IniConfigSource(@"D:\NEWROBOT\" + Client + ".ini");
                string[] Services = ClientConfig.Configs["SERVICES"].GetKeys();
                foreach (string Service in Services)
                {
                    string url = BaseConfig.Configs["CLIENTS"].Get(Client);
                    string param = ClientConfig.Configs["SERVICES"].Get(Service);
                    string html = WC.DownloadString(url + param);

                    // Cargar doc en HPACK
                    HtmlDocument doc = new HtmlDocument();
                    doc.LoadHtml(html);

                    // LINQ para generar imagenes
                    var img = doc.DocumentNode.SelectSingleNode("//img[1]");
                    var src = img.Attributes["src"].Value;
                    string uIMG = url + src;
                    WC.DownloadFile(uIMG, @ImgDir + Client + "\\" + Service + ".png");
                }
                strTimer.Stop();
                TimeSpan ts = strTimer.Elapsed;
                string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);
                strTimer.Reset();
                // WANT TO WRITE HERE Form1.TextBox1.text = "RunTime " + elapsedTime;
            }
        }
    }
}

回答1:

I think, a better way is to handle through events.

Create a class to represent data that you want to pass.

public class ChartCopyProgressEventArgs : EventArgs
{
  public TimeSpan ElapsedTime { get; set; }
  //you can add more prop.s here
}

In "chartscopier" create an event to report progress.

class chartscopier
{
 public static event EventHandler<ChartCopyProgressEventArgs> Changed;
 public static void CopyGraph(object data)
 {
 ...
 if (Changed != null)
 {
   var args = new ChartCopyProgressEventArgs();
   args.ElapsedTime = elapsedTime;
   Changed(null, args);
 }
 }
}

Then in Form1, create a handler for that event.

public Form1()
{
 InitializeComponent();
 chartscopier.Changed += UpdateStatus;
 ...
}

private void UpdateStatus(object sender, ChartCopyProgressEventArgs e)
{ 
    var ts = e.ElapsedTime;
    var elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);
    var str = "RunTime " + elapsedTime;

    if (TextBox1.InvokeRequired) {
        TextBox1.Invoke(() => {TextBox1.text = str;});
    } else {
         TextBox1.text = str;
    }
}


回答2:

You need to pass the form to that function so you have access to it, then write a public function on the form to modify/get the text box. Make sure the two functions are checking if invoke is required.



回答3:

You need to pass a reference you want chartscopier.CopyGraph to manipulate directly to the method so it can be within scope. Your CopyGraph(object data) signature should be more like CopyGraph(object data, TextBox aTextBox)

Then you can call it from your Form1's instance like

chartscopier.CopyGraph(data,this.textBox1)


回答4:

This example will show you how to access form elements from other class:

public partial class Form1 : Form
    {       
        private void button1_Click(object sender, EventArgs e)
        {
            FormCopier fc = new FormCopier();
            fc.PopulateTest(this.textBox1);
        }
    }  

And in other class..

class FormCopier
{
    public void PopulateTest(TextBox t)
    {
        t.Text = "Demo";
        t.Refresh();
    }
}