3

我有一个名为 form1 的表单,当我尝试从 class1 获取 form1 中的文本框中的文本时,我还有一个名为 class1 的类。从字面上看,我花了两天时间才弄清楚获取文本的正确方法。

见下面的代码:

我有以下课程:

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 创建公共 getter 和 setter 时将 textbox1 公开,我需要做的就是创建一个 form1 引用。

所以我的问题是,为什么展览 B 仅使用对表单的引用,但展览 A 需要对表单的引用和被访问的变量才能公开工作。为什么这是……我错过了什么?

4

3 回答 3

3

Exhibit A 依赖于引用该组件的公共成员。如果组件不存在,则设计器生成的字段 ( this.textBox1) 也将不存在,程序将无法编译。

图表 B 按名称查找组件。如果组件不存在,程序将编译得很好,但在运行时会失败。

在这种情况下,编译错误通常优于运行时错误,但正确的选择最终取决于您的质量要求。

于 2013-07-12T13:31:38.307 回答
1

为了更好地了解幕后发生的事情我建议您安装ILSpy。从 GAC打开并查看课程。System.Windows.FormsControl

展示 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;
}
于 2013-07-12T21:39:34.860 回答
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;

这里的重点是实际变量对类保持私有,而您公开的只是通过成员函数。这是封装。

我强烈建议您阅读基本的面向对象原则 - 查找有关它的在线教程或其他内容!祝你好运。

于 2013-07-12T13:34:01.863 回答