我有一个名为form1的表单,我还有一个名为class1的类 当我试图从class1中的form1中的文本框中获取文本时。它花了两天的时间来弄清楚获取文本的正确方法。
请参阅以下代码:
我有以下课程:
class Class1
{
// field to hold the Form1 object reference
private Form1 DataEntryForm;
// Class1 constructor
public Class1(Form1 form)
{
// store the Form1 object reference
DataEntryForm = form;
}
public void gettext()
{
//the following doesn't work..
string textintextbox = DataEntryForm.textBox1.text;
//I get the following error => somenamespace.Form1.textBox1 is inaccessible due to its protection
//but the following code works just fine.... why?
textintextbox = ((TextBox)DataEntryForm.Controls.Find("textBox1",true).FirstOrDefault()).Text;
}
}
你可以看到我知道我必须在class1中声明对表单的引用,然后像'myform1refence.textbox1.text'那样访问文本框但是如果你看一下上面的代码就不能用作textbox1是私有的。所以我谷歌就像我被解决了这个以及我去过的每个地方,人们建议我“不应该”使textBox1公开,因为它是糟糕的编程或者其他东西,但我应该创建一个像这样的公共变量
public partial class Form1 : Form
{
public sometype somevariablename {get { return somePrivatevariablename; } set { somePrivatevariablename = value; }}
}
所以我认为这是我应该从class1访问我的textbox1的正确方法所以我写了以下
public partial class Form1 : Form
{
public TextBox _textBox1 {get { return this.textBox1; } set { this.textBox1 = value; }}
}
所以当我在class1中键入以下内容时,它可以正常工作!
展览A
string textintextbox = DataEntryForm.textBox1.text;
所以有一天我继续编码并接受这个是我问题的最佳解决方案。然后我偶然发现了以下代码:
展览B string textintextbox = ((TextBox)DataEntryForm.Controls.Find("textBox1",true).FirstOrDefault()).Text;
使用上面的代码我不需要将textbox1公开为textBox1创建公共getter和setter所有我需要做的就是创建一个form1引用。
所以我的问题是为什么展览B只能参考表格而是 展览A需要对表格的引用和被访问的变量公开工作。为什么这......我错过了什么?
答案 0 :(得分:3)
Exhibit A依赖于引用该组件的公共成员。如果组件不存在,设计器生成的字段(this.textBox1
)也将不存在,程序将无法编译。
图表B按名称查找组件。如果该组件不存在,程序将编译得很好,但在运行时运行时失败。
编译错误通常比此上下文中的运行时错误更受欢迎,但正确的选择最终取决于您的质量要求。
答案 1 :(得分:1)
为了更好地了解幕后发生的事情,我建议您安装ILSpy。从GAC打开System.Windows.Forms
,然后查看Control
类。
展览B 将起作用,因为Controls
类的System.Windows.Form.Control
属性包含所有控件,而忽略了它们的修饰符:
public Control.ControlCollection Controls
{
get
{
Control.ControlCollection controlCollection = (Control.ControlCollection)this.Properties.GetObject(Control.PropControlsCollection);
if (controlCollection == null)
{
controlCollection = this.CreateControlsInstance();
this.Properties.SetObject(Control.PropControlsCollection, controlCollection);
}
return controlCollection;
}
}
CreateControlsInstance
的位置:
protected virtual Control.ControlCollection CreateControlsInstance()
{
return new Control.ControlCollection(this);
}
因此,System.Windows.Forms.Control.ControlCollection.Find
方法public
会在整个控件集合上搜索指定的控件名称:
public Control[] Find(string key, bool searchAllChildren)
{
if (string.IsNullOrEmpty(key))
{
throw new ArgumentNullException("key", SR.GetString("FindKeyMayNotBeEmptyOrNull"));
}
ArrayList arrayList = this.FindInternal(key, searchAllChildren, this, new ArrayList());
Control[] array = new Control[arrayList.Count];
arrayList.CopyTo(array, 0);
return array;
}
答案 2 :(得分:0)
class Class1
{
public string getText()
{
return DataEntryForm.textBox1.Text;
}
}
可能就是你想要的。 getText
是公开的 - 它可以被类外的东西调用:
Class1 Thingy = new Class1();
string AString = Thingy.getText();
但会阻止您访问班级内部。这是不允许的
string AnotherString = Thingy.textBox1.Text;
这也不会:
TextBox tb = Thingy.textBox1;
但是,您可以将此功能添加到您保持文本框保密的类:
public TextBox GetMyTextBox()
{
return textBox1;
}
你可以在课堂外进行:
string Str = Thingy.GetMyTextBox().Text;
这里的要点是实际变量对于类是私有的,而你公开的只是通过成员函数。这是封装。
我强烈建议您阅读基本的面向对象原则 - 找一个关于它的在线教程或其他东西!祝你好运。