C#错误:对象引用未设置为对象的实例

时间:2011-08-24 18:04:45

标签: c# .net listbox

我尝试制作管理客户联系人的应用。表格非常简单。有:面板(在此面板内是带有名称,电子邮件等的标签)和一个列表框,显示sdf文件中所有已保存的联系人。我有一个大问题。我想通过另一个类中的方法刷新列表框内容。我将列表框设置为public,调试器在项目构建期间没有显示错误。加载表单时,会提示此消息(通过try-catch异常):“对象引用未设置为对象的实例。”。我尝试以不同的方式完成这个项目 - 所有内容都写在一个类中。这是代码:

database.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlServerCe;

namespace Contacts
{
    class Database
    {
        public static void RefreshListBox()
        {
            SqlCeConnection connection = null;
                try
                {
                var form1 = Form.ActiveForm as Form1;
                connection = new SqlCeConnection("Datasource = C:\\Kontakty.sdf");
                connection.Open();
                SqlCeCommand command = new SqlCeCommand("SELECT * FROM Contacts", connection);
                SqlCeDataReader reader = command.ExecuteReader();
                while (reader.Read())
                {
                    form1.listBox1.Items.Add(reader.GetString(0) + " " + reader.GetString(1));
                }
                }
                catch(Exception exc)
                {
                    MessageBox.Show(exc.Message);

        }
    }
}

Form1.cs的

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Contacts
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Database.RefreshListBox();
        }


    }
}

有谁在这里知道什么是错的?

PS:kontakty =联系人(捷克语; - ))

3 个答案:

答案 0 :(得分:0)

Form.ActiveForm可能为null,因为From1仍然被加载,可能尚未显示,因此无效。

答案 1 :(得分:0)

这可能会有所帮助:

public static void RefreshListBox(ListBox listBox)
  ...
  while (reader.Read())
  {
    listBox.Items.Add(reader.GetString(0) + " " + reader.GetString(1));
  }

然后:

private void Form1_Load(object sender, EventArgs e)
{
  Database.RefreshListBox(this.listBox1);
}

除此之外,你真的不应该将表单或列表框传递到数据库类中。它应该是另一种方式 - 你的表单应该从类中获取数据并在那里填充列表框。

答案 2 :(得分:0)

我要做的第一件事就是将对列表框的引用传递给RefreshListBox()函数。

您的课程没有理由对Form1有任何了解或参考。

以您的形式尝试:

 private void Form1_Load(object sender, EventArgs e)
 {             
      Database.RefreshListBox(this.listBox1); 
 } 

这是你班上的:

public static void RefreshListBox(ListBox listbox)             
{                 
      SqlCeConnection connection = null;
      try
      {
           listbox.Items.Clear()    //I assume you may want to refresh?

           connection = new SqlCeConnection("Datasource = "C:\\Kontakty.sdf");
           connection.Open();                     
           SqlCeCommand command = new SqlCeCommand("SELECT * FROM Contacts", connection);
           SqlCeDataReader reader = command.ExecuteReader(); 
           while (reader.Read())   
           {
               listbox.Items.Add(reader.GetString(0) + " " + reader.GetString(1));
           }
      }
      catch(Exception exc)
      {                         
          MessageBox.Show(exc.Message);                  
      }
} 

我遗漏了很多东西(比如坚持选定的项目),但你明白了。

此外 - 如果未指定其顺序,请不要对SQL返回值使用字段索引。按名称调用字段(我知道您不能使用CE SqlDataReader)或更好:在SQL语句中指定它们(及其顺序)。你永远不知道DB何时会被移动或重新生成,并且“Select * From ...”中的默认顺序将被激活,如果在更高版本中添加了字段,那么你只是浪费带宽/数据空间来返回它们的值如果你不打算使用它们。