【问题标题】:Sending information to a textbox from a class to a form [closed]将信息从类发送到文本框到表单[关闭]
【发布时间】:2012-11-08 20:05:48
【问题描述】:

几天前我问了一个关于在课堂上的表单上填充列表框的问题。它有效并且很棒!但是我现在想对文本框或标签做同样的事情。该问题的答案如下:

您正在做的是创建表单的一个新实例 - 我想 您正在尝试在现有表单的列表框中添加项目?

如果是这样,请这样做。

使用列表框在表单上创建一个函数,例如:

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

然后,在类中(记得添加 using System.Windows.Forms 参考)

   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");

      }
 }
    }

这很好用。现在我想对文本框做同样的事情。我想知道是否有人可以解释或是否有人对此有链接?

我有一个表格和一个班级。该表单创建了一个类的新实例并在该类中启动一个方法,例如数学方程式 4+4;我希望从类中的方法中将答案“8”显示在 form1 上的文本框或标签中。

【问题讨论】:

  • 那个答案很糟糕;从一开始就是糟糕的设计......
  • 您想将文本设置为您班级的 TextBox 吗?
  • @DmitryMartovoi 这个答案比这个更好,但仍然没有它应该的那么好。在这种特殊情况下,父表单应该订阅子表单上的事件;孩子不应该参考父母。也就是说,我们不知道“其他类”是否是子窗体。
  • 是的,我知道,但它是一个简单的解决方案。

标签: c# winforms forms instances


【解决方案1】:

您通过编辑描述的是一个模型,其中您的Form 使用另一个类。正在使用的类应该不知道Form、它的控件,或者它的计算结果如何可能被使用。

你的其他类不应该找到表单,它不应该调用表单的任何方法或字段,或任何东西。它应该做的只是返回一个值:

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

然后表单可以做这样的事情:

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

另一个类应该负责进行计算,创建结果,但不根据这些结果更新用户界面。所有的用户界面逻辑都应该包含在Form 类中。

【讨论】:

    【解决方案2】:

    把这个放到Form1.cs中:

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

    在类文件中:

    frmTemp.SetText("XYZ");
    

    【讨论】:

      【解决方案3】:

      遍历所有打开的表单似乎是一种……新颖的……获取相关表单的方法。

      相反,您应该保留对表单的引用,直到最终关闭它,并通过它直接访问表单上的变量(如列表框和文本框)。

      所以,在你创建表单的地方,做类似的事情

      Form1 form1 = new Form1();
      

      // 打开对话框或您将要对 form1 执行的任何操作

      // 当你需要访问一个文本控件时:

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

      如果 doStuff 是从模型(模拟现实世界行为的某些方面的类)中发生的,那么您遵循的设计模式很糟糕。

      模型不应该知道它们是如何呈现的。相反,在典型的 WinForms 应用程序中,父窗体可能会保存变量 form1。在较新类型的 UI 项目中,您会看到 MVC 或 MVVM 模式来分离模型、视图(表示/表单)和控制器(流控制)。也可以使用 WinForms 遵循 MVC 模式,尽管我见过的许多/大多数 WinForms 应用程序不这样做。

      【讨论】:

      • 将控件(例如文本框)公开用于表单通常也被认为是糟糕的设计。没有使用openforms那么糟糕,但仍然很糟糕。另请注意,这个其他类可能不适合引用表单。 (我们没有足够的知识来回答这个问题。)有可能另一个类应该订阅一个事件,表单应该订阅一个事件,另一个类应该向表单返回一个值,或者其他几个可能的之一选项。
      • @Servy:我可能在您发表评论后添加到我的答案中。我同意,因为这会导致意大利面条式代码,但仅仅提供一个函数包装器来获取/设置并不能解决设计问题,而只是添加了一层相同的糟糕设计模式。正确的方法是使用 MVC,限制可访问性,以便模式的每个部分只能访问完成工作所需的内容。
      • 是的,我同意您在编辑中添加的内容。到目前为止,我大多只是坚持自己说在各种提议的解决方案中不应该做的事情,因为 OP 没有提供足够的信息/上下文来提供我认为合适的解决方案。如果/当他这样做时,我会添加一个答案。毋庸置疑,它不会涉及表单上的 get/set 方法,就像公开公开内部控制一样。
      • 只是在 ping 你。 OP编辑了这个问题来解释他的实际用例,所以我有now written an answer
      【解决方案4】:

      如果您使用的是 Visual Studio,您可以指定每个成员的可见性,例如privatepublicprivate 是默认值(如果我没记错的话)。

      如果您将其更改为 public,那么您可以执行以下操作:

      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";
        }
       }
      }
      

      编辑 1
      更好的方法是告诉 Form1 它需要更新一些东西,它如何呈现数据与调用该方法的类无关。

      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 现在负责更改它所拥有的控件,而不是由其他(可能是不相关的)类来操作它们。 这将所有 UI 逻辑encapsulated 保留在 Form1 中,所有业务逻辑都可以保存在其他地方。

      【讨论】:

      • 这是一种设计非常糟糕的方法,并且变得更糟......
      • “生成成员”是我的想法,默认设置为 true,因此默认情况下可以公开访问表单的成员。
      • @Servy - 是的,这不是最好的设计,但它确实回答了如何从表单外部将文本设置到文本框中的问题。
      • 当您看到有人在使用设计不佳的方法时遇到问题,您应该帮助他们想出一个设计合理的方法,以可持续、可维护和有效的方式解决问题,以便他们传播好的技术而不是坏的。对于刚刚学习特定范式并且可能会模仿他给出的任何示例的人来说尤其如此。默认情况下将所有表单的所有成员设置为公开是一个糟糕的想法。作为一般规则,您不应该将您的控件暴露在外部,并非常警惕任何建议的解决方案。
      • @Servy - 希望上面的编辑展示了一个更好的例子来说明如何实现这一点
      猜你喜欢
      • 1970-01-01
      • 2014-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-02
      • 2021-01-23
      • 1970-01-01
      • 2012-12-26
      相关资源
      最近更新 更多