C# C从将关闭的弹出窗体中获取变量

C# C从将关闭的弹出窗体中获取变量,c#,.net,winforms,user-controls,C#,.net,Winforms,User Controls,我用从主窗体创建的userControls数组填充了一个窗体。我需要能够从主窗体访问这个userControls数组,一旦按下按钮时关闭弹出窗口。如果我填写表单,然后在不关闭弹出窗口的情况下按下主表单上的按钮,则会显示值。但是,如果关闭弹出窗口,则值不存在。我的主窗体是静态的,所以我可以在其他窗体中使用它的变量 弹出窗口的代码: public ScanChannel[] controls; public ScanListSetup() { InitializeC

我用从主窗体创建的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);
        }
因此,如果我在弹出窗体仍然打开的情况下单击scanButton,调试写线将输出正确的值。但是,如果在单击弹出窗体上的“完成”按钮后关闭窗体,调试writeLine将输出Test:而不输出其他内容


在此方面的任何帮助都将不胜感激。谢谢。

您的问题本质上归结为将数据从辅助窗口(即“弹出式”窗口)发送到创建数据的主窗口。无论您使用的是Windows控件对象还是字符串之类的简单数据类型,这都无关紧要,因此我将使用一个简单的示例来说明如何处理这种情况

假设有一个主窗体,看起来像这样。它有一个打开的按钮和一个文本框

当您单击“打开”时,它将打开此辅助输入窗口,您的弹出窗口如下所示:

public delegate void DataTransfer(string data);
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();
    }
}
public class DataToPass
{
    public string TextBoxText { get; set; }

    public string SomeOtherData { get; set; }

    // Other stuff you want...
}
现在的想法是这样的。单击“打开”打开输入表单,让用户在文本框中输入一些文本。单击OK按钮后,它将关闭输入窗口,并在主窗口中显示用户输入的文本。记住,此时输入窗口关闭,这与您的情况相同

所以我会利用这个机会来实现这个目标。委托允许您在windows之间传输您想要的数据

在我的主要声明中,我将声明一个签名如下的公共代表:

public delegate void DataTransfer(string data);
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();
    }
}
public class DataToPass
{
    public string TextBoxText { get; set; }

    public string SomeOtherData { get; set; }

    // Other stuff you want...
}
也就是说,此委托表示一个接受单个字符串参数并具有void返回类型的方法。其思想是让辅助输入窗口在Main中“调用”一个方法,该方法接受一个字符串参数。因此,如果有一种方法可以让我们从输入调用驻留在Main中的方法,并传递一个字符串,那么我们可以在输入窗口中获取用户输入文本,并将其传递到主窗口。到目前为止和我在一起

现在,如果我在Main中编写一个这样的方法,并让它从输入中调用,那么应该可以实现我们的目标。这里,txtDisplay是主窗体中的文本框

为了实现这一点,我将以如下的主形式定义DataTransfer类型的委托,并向其注册ReceiveInput方法。您的主要表单代码应该如下所示:

public delegate void DataTransfer(string data);
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();
    }
}
public class DataToPass
{
    public string TextBoxText { get; set; }

    public string SomeOtherData { get; set; }

    // Other stuff you want...
}
BtnOpen是主窗体中的打开按钮,单击它时,它将委托传递给输入窗体,然后打开它。因此,我们需要相应地修改输入表单:

在这里,我们修改构造函数,使其接受DataTransfer类型的委托,并将其设置为相同类型的本地实例。然后,单击输入表单上的BtnOK,我们接收用户输入的文本,并将该文本传递给所述代理并调用它。”调用“”与在主窗体中调用方法相同。此时,您可以如上所示关闭输入窗口,并且仍然可以从主窗体访问用户输入字符串数据

您可以使用相同的方法,并且可以传递控件而不是字符串。但是,来回传递一组控件并不是最好的方法,因此理想情况下,您可以从弹出窗口中的这些控件中提取所需的数据,并且只传递所述数据,而不是整个控件

编辑:OP发布错误代码后

好的,这是你的问题。testUserControl类不是常规类,而是从UserControl派生的控制元素。否则,将使用GUI元素。您不应该使用GUI元素来传递数据。因为,当你控制arr[i].getText;,它试图从textItem获取文本,但textItem是一个TextBox控件,此时不存在,因为您关闭了窗口。请记住,您执行委托。仅调用一次,此时*必须将所有数据发送回主窗口*

您应该做的是,只需定义一个类来保存所有要传递到主节点的数据。例如,类似这样的事情:

public delegate void DataTransfer(string data);
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();
    }
}
public class DataToPass
{
    public string TextBoxText { get; set; }

    public string SomeOtherData { get; set; }

    // Other stuff you want...
}
现在,不是传递testUserControl数组,而是传递DataToPass数组。这样,在主窗体中,您不必执行以下操作:

controlArr[i].getText();
相反,您只需执行以下操作:

controlArr[i].TextBoxText;
其中controlArr现在是DataToPass类型的数组


简单地说,传递从UserControl派生的控件不是一个好主意。只需创建一个能够保存所有要传递的数据的类,并将其传递回main一次。

感谢您的回复。不幸的是,我仍然有同样的问题
尝试此操作后出现问题。如果我删除关闭并保持弹出窗口打开,我的主窗体可以访问数据。如果我关闭弹出窗口,它是空的。我检查并调用了ReceiveData函数,但这就像弹出窗口消失后一样;由于缺少更好的术语,因此在我的main中取消了对变量的引用。对不起,我没有很好地解释这个问题。我很感谢你的帮助。也许分享你的代码,你可以上传到github。因为这应该是可行的,所以在关闭弹出窗口之前,请调用该方法并将值传递给Main,此时打开或关闭弹出窗口并不重要。不幸的是,我无法按照公司政策发布我的代码。您认为问题可能是因为C中的数组是引用类型吗?因此,通过删除弹出表单,我正在删除被引用的数组。如果我只发送一个字符串而不是一个数组,它就可以正常工作。我根本无法调试一个看不见的代码。如果您不能按照公司政策共享代码,人们通常会创建一个模拟代码示例,在不共享实际代码的情况下复制问题;在C语言中,它创建一个引用。因此,当原始数据消失时,重复数据也消失了。如果您正在做类似的事情,请尝试使用某个数组=另一个数组;