Sending information to a textbox from a class to a

2019-09-21 07:04发布

问题:

I asked a question a couple of days ago about populating a listbox on a form from a class. It works and was great! However I now want to do the same with a textbox or a label. The answer from that question is below:

What you are doing is creating a new instance of the form - I presume you are trying to add items in a listbox on an existing form?

If so do this.

Create a function on the form with the listbox like:

    public void addItemToListBox(string item)
    {
         listBox1.Items.Add(item);
    }

Then, in the class (remember to add the using System.Windows.Forms reference)

   public void doStuff()
    {
 //Change Form1 to whatever your form is called
 foreach (Form frm in Application.OpenForms)
 {
      if (frm.GetType() == typeof(Form1))
      {
           Form1 frmTemp = (Form1)frm;
           frmTemp.addItemToListBox("blah");

      }
 }
    }

This works well. Now I want to do the same with a textbox. I was wondering if someone could explain or if someone has a link on this?

I have a form and a class. The form makes a new instance of the class and initiates a method in the class, say a maths equation 4+4; I want the answer, "8" to then be shown in a textbox or label on form1, from the method in the class.

回答1:

What you are describing, with your edit, is a model in which your Form uses another class. The class that is being used should have no knowledge of the Form, it's controls, or how the result of its calculation could possibly be used.

Your other class shouldn't find the form, it shouldn't call any methods or fields of the form, or anything. What it should do is just return a value:

public class OtherClass
{
    public int Add(int first, int second)
    {
        return first + second;
    }
}

Then the form can do something like this:

private void button1_Click(object sender, EventArgs e)
{
    //create an instance of the other class
    OtherClass other = new OtherClass();
    //call it's add method, and then use the result to set the textbox's text
    textbox1.Text = other.Add(4, 4).ToString(); 
}

The other class should be responsible for doing the calculations, creating a result, but not updating the user interface based on those results. All of the user interface logic should be contained in the Form class.



回答2:

Put this in Form1.cs:

public void SetText(string text)
{
    textBox1.Text = text;
}

And in the class file:

frmTemp.SetText("XYZ");


回答3:

Looping through all open forms seems like a ... novel ... way to get the form in question.

Instead, you should keep a reference to the form until you finally close it, and access variables on the form (like list boxes and text boxes) directly through that.

So, where you create the form, do something like

Form1 form1 = new Form1();

// Open the dialog or whatever you are going to do with form1

// When you need to access a text control:

form1.textBox1.Text = "Some value"; // Assumes the control is called textBox1

If doStuff is happening from a model (a class that models some aspect of real-world behavior), you are following a poor design pattern.

Models should have no idea of how they are presented. Instead, in a typical WinForms application, a parent form would likely hold the variable form1. In newer types of UI projects, you would see a MVC or MVVM pattern to separate the Model, the View (presentation/forms) and Controller (flow control). One can also follow an MVC pattern with WinForms, though many/most WinForms applications I have seen don't do that.



回答4:

If you are using Visual Studio, you can specify the visiblity of each member, e.g. private or public. private is the default (if i remember correctly).

If you change this to public, then you could do the following:

public void doStuff()
{
 //Change Form1 to whatever your form is called
 foreach (Form frm in Application.OpenForms)
 {
  if (frm is Form1)
  {
       var frmTemp = (Form1)frm;
       frmTemp.listBox1.Items.Add("blah");
       frmTemp.textBox1.Text += "hello world";
  }
 }
}

Edit 1
A better approach, would be to tell Form1 that it needs to update something, how it presents the data is of no concern to the class which is invoking the method.

private Form1 _FindForm()
{
   //assuming you can use Linq
   return Application.OpenForms.OfType<Form1>().Single();
}

public void displaySomething()
{
   var form = _FindForm();
   form.displaySomething();
}

public class Form1
{
  public void displaySomething()
  {
    //add an item to the list box
    listBox1.Items.Add("foo");

    //and change the text somewhere
    textBox1.Text += "bar";
  }
}

Form1 is now responsible for changing the controls it holds, rather than other - possibly - unrelated class manipulating them. This keeps all of the UI logic encapsulated into Form1, and all the business logic can be held elsewhere.