从另一种形式调用方法的问题

时间:2015-12-07 23:43:00

标签: c# winforms

我发现了一些关于在其他表单中使用方法的好帖子,并尝试在我的代码中实现它们,但我得到一个空对象错误(具体来说,frmAddMaterials对象为null)。代码编译正常,尝试使用第二个窗体上的创建材料按钮时发生错误。

我的第一个表单有一个数组来保存材料信息。当用户单击第一个表单上的链接时,系统会提示第二个表单,如果他们感兴趣的材料不在设计中,他们可以输入自定义材料信息。单击表单上的“添加材料” 2,我想在第一个表单上运行RefreshMaterials()方法,它根据第二个表单中的信息在数组中创建一个新条目。

Form1:

public partial class frmSnapFitMain : Form
{
    public frmMat frmAddMaterials;
    public Materials[] material = new Materials[20]; 
    Image[] problemtype = new Image[7]; 


private void linkLabel1_LinkClicked_1(object sender,LinkLabelLinkClickedEventArgs e)
    {
        frmMat frmAddMaterials = new frmMat(this);
        frmAddMaterials.Show();
    }    


public void RefreshMaterials()
    {
        material[Materials.MaterialCount] = new Materials(frmAddMaterials.txtName.Text, Double.Parse(frmAddMaterials.txtFlex.Text), Double.Parse(frmAddMaterials.txtFriction.Text), Double.Parse(frmAddMaterials.txtStrain.Text)); //little m, materials here is for specific instance
        cboxMatSelect.Items.Add(frmAddMaterials.txtName.Text);
        frmAddMaterials.txtName.Text = ""; //reset fields
        frmAddMaterials.txtFlex.Text = "";
        frmAddMaterials.txtFriction.Text = "";
        frmAddMaterials.txtStrain.Text = "";
    }
}

表格2:

 public partial class frmMat : Form
{
    private readonly frmSnapFitMain _form1;

    public frmMat(frmSnapFitMain Form1)
    {
        InitializeComponent();
        this._form1 = Form1;
    }

    public void btnCreate_Click(object sender, EventArgs e)
    {
        this._form1.RefreshMaterials();
        this.Close();
    }

    public void frmMat_Load(object sender, EventArgs e)
    {

    }
}

1 个答案:

答案 0 :(得分:0)

linkLabel1_LinkClicked_1方法中,您声明了frmMat的新实例。这个实例恰好与全局变量具有相同的名称,但它是一个本地变量,当您退出该方法时它会消失。

 private void linkLabel1_LinkClicked_1(object sender,LinkLabelLinkClickedEventArgs e)
{
    // This is not the global variable frmAddMaterials. 
    // It is a local one to this method
    frmMat frmAddMaterials = new frmMat(this);
    frmAddMaterials.Show();
} 

当然这意味着您在 RefreshMaterials 中使用了从未初始化的全局变量

您只需要删除局部变量的声明并初始化全局变量

private void linkLabel1_LinkClicked_1(object sender,LinkLabelLinkClickedEventArgs e)
{
    // This initializes the global variable
    frmAddMaterials = new frmMat(this);
    frmAddMaterials.Show();
} 

说使用全局变量并测试变量是否已正确初始化时,使用'防御性编程态度'始终是一个好习惯。

public void RefreshMaterials()
{
    if(frmAddMaterials != null)
    {
        material[Materials.MaterialCount] = new Materials(.....)         
        cboxMatSelect.Items.Add(frmAddMaterials.txtName.Text);
        frmAddMaterials.txtName.Text = ""; //reset fields
        frmAddMaterials.txtFlex.Text = "";
        frmAddMaterials.txtFriction.Text = "";
        frmAddMaterials.txtStrain.Text = "";
    }
}

我还建议订阅FormClosing frmAddMaterials事件,以便在表单关闭时将您的实例设置为null

private void linkLabel1_LinkClicked_1(object sender,LinkLabelLinkClickedEventArgs e)
{
    if(frmAddMaterials != null)
    {
        frmAddMaterials = new frmMat(this);
        frmAddMaterials.Show();
        frmAddMaterials.FormClosing += frmMaterialsClosing;
    }
}    
private void frmMaterialsClosing(object sender, CancelEventArgs e)
{
    frmAddMaterials = null;
}

这允许您重新启动'循环',因为再次单击linklabel时,您的全局变量为null,您可以将其重新初始化为在linklabel click事件处理程序中创建的新实例。