首页 > 解决方案 > Trouble understanding scope of Variables between forms

问题描述

Being new to c# I am having trouble understanding how to read from a variable when in a different form.

Form1:

namespace SPTimesheets
{
    public partial class Form1 : Form
    {
        public DataTable dtWP = new DataTable("WorkPackHours");
 
       private void GetWorkPackData()
        {
        ...............
        di.Fill(dtWP);
        ................
        }
}

Form2:

namespace SPTimesheets
{
    public partial class WorkPacks : Form
    {
        public WorkPacks()
        {
            InitializeComponent();
        }

        private void WorkPacks_Load(object sender, EventArgs e)
        {
            dataGridView1.DataSource = Form1.dtWP;
        }
    }
}

I've been reading everything I can find about scope, but I'm obviously missing something. How do I access dtWP from a different form? The error is "An object reference is required for the non-static field, method or property Form1.dtWP.

标签: c#winforms

解决方案


It is important to understand what an instance is. We can say:

Form1 foo = null;

Here we have created a reference to Form1 but have not assigned it a value. We've said there is a variable named "foo" and it is of type Form1, but we didn't assign it an instance of the object (Form1). Since there is no instance foo will be null.

This is basically what is happening in your WorkPacks Form. WorkPacks can see that there is an object of type Form1, but just because it knows the object type doesn't mean it knows the values.

From the looks of your code WorkPacks doesn't need to know about Form1, it just needs the DataTable from Form1. To achieve that we can pass the DataTable to WorkPacks when the form is created.

namespace SPTimesheets
{
    public partial class Form1 : Form
    {
       public DataTable dtWP = new DataTable("WorkPackHours");
 
       private void GetWorkPackData()
       {
            di.Fill(dtWP);
       }

       private void btnOpenWorkPacksForm(object sender, EventArgs e)
       {
            // This is where we create a new instance of WorkPacks form and pass the DataTable to the form.
            WorkPacks wp = new WorkPacks(dtWP);
            wp.Show();
       }
}

Now we can overload the constructor to pass in the DataTable.

namespace SPTimesheets
{
    public partial class WorkPacks : Form
    {
        private DataTable _dtWP;
        public WorkPacks()
        {
            InitializeComponent();
        }

        public WorkPacks(DataTable dt)
        {
            InitializeComponent();
            _dtWP = dt; // set our local _dtWP DataTable to the DataTable passed from Form1 (dt)
        }

        private void WorkPacks_Load(object sender, EventArgs e)
        {
            dataGridView1.DataSource = _dtWP;
        }
    }
}

This will be a pretty standard way to pass your values to Forms. If you need a lot of values from Form1 then it is possible to pass the entire form to the new form. However, I would urge against this. It would be better to create a class that has properties of the values you want to pass.

public class MyFormProperties
{
    public DataTable dtwp {get;set;}
    public string exampleProperty {get;set;}
}

Then create an instance of this in your starting form and pass it to the new form through the constructor.

namespace SPTimesheets
{
    public partial class Form1 : Form
    {
       private MyFormProperties _formProperties = new MyFormProperties();
 
       private void GetWorkPackData()
       {
            _formProperties.dtwp.Fill(dtWP);
       }

       private void btnOpenWorkPacksForm(object sender, EventArgs e)
       {
            WorkPacks wp = new WorkPacks(_formProperties);
            wp.Show();
       }
}

namespace SPTimesheets
{
    public partial class WorkPacks : Form
    {
        private MyFormProperties _formProperties;
        public WorkPacks()
        {
            InitializeComponent();
        }

        public WorkPacks(MyFormProperties properties)
        {
           InitializeComponent();
            _formProperties = properties; 
        }

        private void WorkPacks_Load(object sender, EventArgs e)
        {
            dataGridView1.DataSource = _formProperties.dtwp;
        }
    }
}

推荐阅读