我有一个表单,其中填充了从主表单创建的userControls数组。按下按钮后,一旦弹出窗口关闭,我需要能够从主窗体访问此userControls数组。如果我填写表单,然后在不关闭弹出窗口的情况下按主表单上的按钮,则会显示这些值。但是,如果我关闭弹出窗口,则不存在这些值。我的主要形式是静态的,因此我可以将其变量用于其他形式。
弹出代码:
public ScanChannel[] controls;
public ScanListSetup()
{
InitializeComponent();
int numChans = Convert.ToInt32(Form1.Self.numChannels.Text);
controls = new ScanChannel[numChans];
// Create the UserControls
for(int i = 0; i < numChans; i++)
{
controls[i] = new ScanChannel();
}
// Place them
for (int i = 0; i < numChans; i++)
{
controls[i].Location = new Point(13,(35+25*(i)));
this.Controls.Add(controls[i]);
}
doneButton.Location = new Point(82, 35 + (25 * (numChans + 1)));
this.Size =new Size(280, 110 + (25 * (numChans + 1)));
}
private void doneButton_Click(object sender, EventArgs e)
{
Form1.Self.setChannelsToScan(controls);
}
我需要以主要形式访问controls
数组。主要形式的代码如下:
private ScanChannel[] channelsToScan;
private void configureScanListButton_Click(object sender, EventArgs e)
{
var form = new ScanListSetup();
form.Show(this);
scanListConfigured = true;
this.channelsToScan = new ScanChannel[Convert.ToInt32(numChannels.Text)];
}
public void setChannelsToScan(ScanChannel[] arr)
{
for (int i = 0; i < arr.Length; i++)
{
this.channelsToScan[i] = arr[i];
}
}
private void scanButton_Click(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine("Test: " + this.channelsToScan[0].getDeviceType());
// THIS PRINTS AN EMPTY STRING
}
因此,如果在弹出表单仍处于打开状态时单击scanButton
,则Debug writeLine将输出正确的值。但是,如果我在弹出菜单上单击doneButton
后关闭了该表单,则Debug writeLine输出Test:
便没有其他内容。
任何对此的帮助将不胜感激。谢谢。
答案 0 :(得分:1)
您的问题实质上可以归结为将数据从辅助窗口(“弹出”窗口)发送到创建它的主窗口。无论您使用的是Windows Control
对象还是诸如string
之类的简单数据类型都没有关系,因此,我将使用一个简单的示例来说明如何处理这种情况。>
假设您有一个Main
格式的表格,如下所示。它具有一个OPEN
按钮和一个TextBox
。
单击OPEN
时,它会打开以下辅助输入窗口(您的弹出窗口),如下所示:
现在的想法是这样。您单击OPEN
并打开Input
表单,然后让用户在此处的TextBox
中输入一些文本。单击OK
按钮后,它应关闭Input
窗口,并在Main
窗口中显示用户输入的文本。请记住,此时Input
窗口已关闭,这与您的情况相同。
因此,我将利用Delegates来实现此目标。 delegate
使您可以在所需的窗口之间传输数据。
在我的Main
中,我将声明一个public
代表,其签名如下:
public delegate void DataTransfer(string data);
也就是说,此delegate
表示一个采用单个string
参数并具有void
返回类型的方法。想法是让辅助Input
窗口在Main
中“调用”一个方法,该方法接受一个string
参数。因此,如果有一种方法可以从Main
调用位于Input
中的方法并传递string
,那么我们可以在{{ 1}}窗口,并将其传递到Input
窗口。到目前为止和我在一起?
现在,如果我在Main
中编写这样的方法,并从Main
中调用它,那应该可以实现我们的目标。在这里,Input
是txtDisplay
形式的TextBox
。
Main
要完成此操作,我将以如下所示的public void ReceiveInput(string data)
{
txtDisplay.Text = data;
}
形式定义类型为delegate
的{{1}},并向其中注册DataTransfer
方法。您后面的Main
表单代码应如下所示:
ReceiveInput()
Main
是public delegate void DataTransfer(string data);
public partial class MainForm : Form
{
public DataTransfer transferDelegate;
InputForm inputForm = null;
public MainForm()
{
InitializeComponent();
transferDelegate += new DataTransfer(ReceiveInput);
}
public void ReceiveInput(string data)
{
txtDisplay.Text = data;
}
private void BtnOpen_Click(object sender, EventArgs e)
{
inputForm = new InputForm(transferDelegate);
inputForm.Show();
}
}
表单中的BtnOpen
按钮,当单击它时,它将委托传递给OPEN
表单,然后将其打开。因此,因此,我们现在需要修改Main
表单:
Input
在这里,我们修改构造函数,以使其采用类型Input
的{{1}},并将其设置为相同类型的本地实例。然后,在public partial class InputForm : Form
{
DataTransfer transferDel;
public InputForm(DataTransfer del)
{
InitializeComponent();
transferDel = del;
}
private void BtnOK_Click(object sender, EventArgs e)
{
string data = txtInput.Text;
transferDel.Invoke(data);
Close();
}
}
表单上单击delegate
,我们接受用户输入的文本,并将该文本传递给所说的DataTransfer
并调用它。 “调用”与以BtnOK
形式调用方法相同。此时,您可以Input
delegate
窗口,如上所示,您仍然可以从Main
表单访问用户输入的Clsoe()
数据。>
您可以使用相同的方法,并且可以使用Input
来代替字符串。但是,这不是来回传递一堆控件的最佳方法,因此理想情况下,您将从弹出窗口中的那些控件中提取所需的数据,然后仅传递所述数据,而不是整个控件。>
编辑:OP发布了错误的代码之后。
好的,这是您的问题。 string
类不是常规类,而是从Main
派生的控制元素。否则为GUI元素。您不应该使用GUI元素来传递数据。因为,当您执行Controls
时,它会尝试从testUserControl
获取文本,但是UserControl
是controlArr[i].getText();
控件 ,它不会此时存在 ,因为您关闭了窗口。请记住,您只执行一次textItem
,然后 *您必须将所有数据发送回主窗口* 。
您应该做的就是,简单地定义一个类,以保存要传递给主数据库的所有数据。例如这样的东西:
textItem
现在,不传递TextBox
数组,而是传递delegate.Invoke()
数组。这样,在public class DataToPass
{
public string TextBoxText { get; set; }
public string SomeOtherData { get; set; }
// Other stuff you want...
}
表单中,您不必执行以下操作:
testUserControl
相反,您只需执行以下操作即可:
DataToPass
其中Main
现在是类型controlArr[i].getText();
的数组。
简单地,传递从controlArr[i].TextBoxText;
派生的控件不是一个好主意。只需创建一个能够容纳您要传递的所有数据的类,然后将其一次传递回主要对象即可。