我仍然无法获得如何从另一个class.im中访问表单中的控件,因为我的“尝试和错误”方法实际上并没有工作。
有人能给我一个简单的指南吗?
这是我的代码段
Form1中:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
print pr = new print();
pr.p();
}
}
}
这是班级打印:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WindowsFormsApplication2
{
class print
{
public print()
{
}
public void p()
{
Form1 f = new Form1();
f.textBox1.Text = "change text";
}
}
}
正如你所看到的,我试图改变print类中的textBox1属性。但是当我编译它时,我抛出了一个System.StackOverflowException!
我现在感到沮丧,因为我无法从另一个班级访问它。
任何人都可以一步一步地告诉我如何从印刷类中调用它吗?我从互联网上尝试了很多步骤但是我无法得到它。
不过,我确实将文本框的修饰符设为公开。答案 0 :(得分:5)
问题是print.p
方法创建了一个新表单,表单的构造函数再次调用print.p
方法。然后创建另一个新表单,其构造函数再次调用print.p
方法,循环遍历。这就是StackOverflowException
的来源。
解决方案是获得一本教授面向对象编程的书。我知道这可能听起来很讽刺或无益,但是你在Q& A网站上得到的答案都不能充分向你解释为什么你要做的事情是个坏主意。像print
这样的外部帮助程序类应该不能够与表单类的私有成员混淆。相反,您应该在表单类上调用公共方法来进行这些修改。
快速而彻底的修复要求您找到一种方法来在print.p
方法中获取对表单类实例的引用。这是你能够在那个对象上调用方法的唯一方法,而不是创建该类的 new 对象。一种方法是将引用作为参数传递给方法:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
print pr = new print();
pr.p(this);
}
}
class print
{
public print()
{
}
public void p(Form frm)
{
frm.textBox1.Text = "change text";
}
}
另外,作为一个有点不相关的风格说明,您应该知道几乎所有C#(和.NET平台)的编码指南/约定都要求类和方法的名称是PascalCased,而不是camelCased。因此,您的print
类实际上应该命名为Print
。
答案 1 :(得分:1)
最简单的方法是将引用传递给新表单。
print pr = new print(textbox);
public print(Textbox textbox)
{
//do something with textbox.
}
然而,有许多设计模式可以帮助解决这个问题,例如MVP或MVVM。但是,对于您当前的级别,它们可能会稍微提高一些。如果这只是一个简单的小项目,那么上面的代码就可以了。
答案 2 :(得分:1)
由于其他原因,您所拥有的代码存在问题(@CodyGray解释了原因,这就是您获得StackOverflowException
的原因),但通常您可以使用属性来允许访问,而不会暴露实际的TextBox
控制本身;有关详细信息,请参阅this MSDN page,但例如:
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
}
public string FormText
{
get { return textBox1.Text; }
set { textBox1.Text = value; }
}
}
}
然后,为了使用这个属性:
public void p()
{
Form1 f = new Form1();
f.FormText = "change text";
}
编辑:
由于通过评论至少有一个挑剔,并且至少有一个人有足够的动力去发现这一点“很棒”,我还会提供一些不同的方法,仍然使用该属性......
让我们想象一下,您希望set
中的p
文字,我们只会返回我们需要的内容:
public string p()
{
return "change text";
}
那样:
myFormReferenceSomewhereNotInPrintClass.FormText = myPrintClassInstance.p();
或者,您希望get
或使用 p
中的文字:
public void p(string text)
{
//do your thing with the text
}
那样:
myPrintClassInstance.p(myFormReferenceSomewhereNotInPrintClass.FormText);
答案 3 :(得分:1)
您收到StackOverFlowException
,因为您使用此代码在print
中创建Form1
的新实例:
print pr = new print();
然后在print
的构造函数中,您创建一个Form1
的新实例,如下所示:
Form1 f = new Form1();
创建了print
的新实例,该实例创建了Form1
的新实例,该实例创建了print
的新实例,该实例创建了Form1
的新实例,...
您创建了一个无限循环,它会杀死堆栈。
答案 4 :(得分:1)
好的,不知道你为什么要这样做(我不愿意)但是你去了:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
print pr = new print();
pr.p(this);
}
}
public class print
{
public print() {}
public void p(Form1 f)
{
f.textBox1.Text = "change text";
}
}
答案 5 :(得分:0)
你不应该像这样引用跨元素的UI元素属性,这是不好的做法。
更好的方法是:
Form1中:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
print pr = new print();
textBox1.Text = pr.p();
}
}
}
班级打印:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WindowsFormsApplication2
{
class print
{
public print()
{
}
public string p()
{
return "change text";
}
}
}
答案 6 :(得分:0)
public Form1()
{
InitializeComponent();
print pr = new print(this);
pr.p();
}
并在print类中使用它来获取表单
{
Form fpassed;
public print(Form f)
{
fpassed = f;
}
public void p(Form f)
{
f.textBox1.Text = "change text";
}
}
可以通过p(fpasssed)调用它;
答案 7 :(得分:0)
public static MainForm frm;
public MainForm(){
frm = this;
Yes()
}
public Yes(){
frm.textbox1.text = ":D";
}