简体   繁体   中英

A field initializer cannot reference the non-static field, method or property

My app is meant to take a lot of data (400k+ records) from an XLSX spreadsheet, display the data in each sheet in a DataGridView on the form and also allow you to export the selected sheet's data into mySQL.

The export will happen on it's own thread (please note that there is much here that isn't complete):

    private AddItemCallBack AddItemDelegate = new AddItemCallBack(AddItemMethod);
    private delegate void AddItemCallBack(int Total);

    private void lnkExport_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
    {
        sName = ddlTables.SelectedValue.ToString();
        pb = progressBar1;

        var t = new Thread(() => ExportData(sName));
        t.Start();
    }

    private void ExportData(string SheetName = "")
    {
        string sql = "select * from " + String.Format(tablename, SheetName);
        OleDbCommand cmd = new OleDbCommand(sql, conn);

        DataSet ds = new DataSet();
        OleDbDataAdapter da = new OleDbDataAdapter();

        da.SelectCommand = cmd;
        da.Fill(ds);

        connStr = "Data Source=localhost; Initial Catalog=test; User ID=root; Password=Ly@12157114";
        MySqlConnection con = new MySqlConnection(connStr);
        totalRecords = ds.Tables[0].Rows.Count;
        currentRecords = 0;

        foreach (DataRow row in ds.Tables[0].Rows)
        {
            sql = "insert into planet(clubid, clubname, acctno, title, firstname, lastname, cell, email, derp, accttype) " +
            "values(@id, @name, @acct, @title, @fname, @lname, @cell, @email, @derp, @type)";

            MySqlCommand command = new MySqlCommand(sql, con);

            command.Parameters.AddWithValue("@id", row[0]);
            command.Parameters.AddWithValue("@name", row[1]);
            command.Parameters.AddWithValue("@acct", row[2]);
            command.Parameters.AddWithValue("@title", row[3]);
            command.Parameters.AddWithValue("@fname", row[4]);
            command.Parameters.AddWithValue("@lname", row[5]);
            command.Parameters.AddWithValue("@cell", row[6]);
            command.Parameters.AddWithValue("@email", row[7]);
            command.Parameters.AddWithValue("@derp", row[8]);
            command.Parameters.AddWithValue("@type", row[9]);

            try
            {
                con.Open();
                command.ExecuteNonQuery();
                con.Close();
                currentRecords = currentRecords + 1;

                this.Invoke(this.AddItemDelegate, new object[] { totalRecords });
            }
            catch (MySqlException ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

    }

    private static void AddItemMethod(int Total)
    {
        progressBar1.Maximum = Total;

        if (progressBar1.Value < progressBar1.Maximum)
        {
            progressBar1.Value = progressBar1.Value + 1;
        }
        else
        {
            progressBar1.Value = 0;
        }            
    }

VS is complaining that

Error 1 An object reference is required for the non-static field, method, or property 'ImportExcel.Form1.progressBar1' G:\\ImportExcel\\ImportExcel\\Form1.cs 139 13 ImportExcel

For every instance of the progressBar1 control reference in the AddItemMethod void.

I can remove the static type definition from the void, but then I get the same error up on the line defining the CallBack, saying that AddItemMethod is not static.

Really don't know what to do here. Any suggestions?

Make your AddItemMethod non-static and use the constructor to initialize your callback.

private AddItemCallBack AddItemDelegate;
private delegate void AddItemCallBack(int Total); 

private void AddItemMethod(int Total)
{
    progressBar1.Maximum = Total; 
    if (progressBar1.Value < progressBar1.Maximum)
    {
        progressBar1.Value = progressBar1.Value + 1;
    } 
    else 
    { 
        progressBar1.Value = 0; 
    }
}

public Form1()
{
    InitializeComponent();
    AddItemDelegate = new AddItemCallBack(AddItemMethod);
}

progressBar1 is an instance field therefore you can't access it in a static method. You will either need to make it a static field or change AddItemMethod to be an instance method.

  1. Static methods cannot reference instance fields (as opposed to static fields), I suppose that progressBar1 is not static. The solution would be to make AddItemMethod non-static.
  2. You can't set AddItemCallback in a field initializer to an instance method, because field initializers are executed just before constructors and may therefore not depend on non-static members. That's why the compiler complains when you simply change AddItemMethod to an instance method. Initialize the field in a constructor to circumvent that.
private AddItemCallBack AddItemDelegate;

public Form1() 
{
    AddItemDelegate = AddItemMethod;
    // ... other stuff
    InitializeComponents(); // totally guessed, but seems like Form1 is auto generated
}

最简单而又看不到任何代码的方法是将progressBar1作为参数传递给静态方法AddItemMethod

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM