使用搜索文本框中的值过滤数据网格视图列表:’对象引用未设置为对象的实例。

我已经设置了一个文本框来搜索我的数据网格上的名称,但是我收到错误: 'Object reference not set to an instance of an object.'

 List members = new List(); public class Member { public int id { get; set; } public string name { get; set; } public int age { get; set; } public Image image_url { get; set; } } // In a keyup event of the text box (memberGrid.DataSource as DataTable).DefaultView.RowFilter = string.Format("name = '{0}'", searchBox.Text); 

我试图将DataTable更改为ListMember 。 我也尝试使用DataTable前面的List/Member进行转换,但它似乎不起作用。

什么是最好的方法?

编辑:

这就是我将SQL select中的每一行数据添加到列表中的方法。

 members.Add(new Member { id = Convert.ToInt32(reader["id"]), name = reader["name"].ToString(), age = Convert.ToInt32(reader["age"]), image_url = (Image)Properties.Resources.ResourceManager.GetObject(reader["image_url"].ToString()) }); 

要添加到网格,我遍历列表并为每个成员添加一行:

 for (int i = 0; i < members.Count; i++) { memberGrid.Rows.Add(new object[] { members[i].image_url, members[i].name, members[i].age }); } 

由于您没有设置DataGridView DataSource并且它为null,因此当您在此语句中使用它时收到exception: (memberGrid.DataSource as DataTable).DefaultView...

而不是DataGridViewDataGridView添加行,而是将数据分配给其DataSource 。 然后,根据您使用的数据结构,您可以过滤数据。

您可以使用以下任一解决方案:

  • 作为一个选项,要解决问题,您可以将数据加载到DataTable并将其设置为DataGridView DataSource 。 然后可以按照您尝试的方式完成过滤。

  • 此外,如果出于任何原因,您希望拥有List并对其应用filter,则在加载数据并转换为List ,将列表保存在List members;等表单成员字段中List members; 然后使用linq进行过滤:

     dataGridView1.DataSource = members.Where(x=>x.Name ==searchBox.Text).ToList(); 

有关详细信息,请阅读post中的以下部分。

为什么我收到NullReferenceException

如果DataSource为null或DataSource不是DataTable ,则以下代码行将抛出NullReferenceException

 (memberGrid.DataSource as DataTable).DefaultView.RowFilter = ... 

在您的情况下,您通过添加行来填充数据库并且没有使用其数据源,因此DataSource为null且上面的代码抛出exception。

要查找有关如何调试NullReferenceException更多信息,请查看什么是NullReferenceException,以及如何解决它? 。

加载数据

你提到过:

这就是我将SQL select中的每一行数据添加到列表中的方法。

 members.Add(new Member { id = Convert.ToInt32(reader["id"]), name = reader["name"].ToString(), ... 

看来你正在使用SQL查询和SqlDataReader 。 那么你不需要使用ListDataTable就足够了。 您可以将代码更改为以下代码以加载数据:

 public DataTable GetData() { var dt = new DataTable(); var cn = @"Your Connection String"; var cmd = @"Your Select Command"; using (var da = new SqlDataAdapter(cmd, cn)) da.Fill(dt); return dt; } 

注意:如果由于任何原因您有兴趣继续使用List ,请重构您的代码以返回GetDataList

 public List GetData() { var dt = new DataTable(); var cn = @"Your Connection String"; var cmd = @"Your Select Command"; using (var da = new SqlDataAdapter(cmd, cn)) da.Fill(dt); return dt.AsEnumerable().AsEnumerable().Select(r=>{ id = r.Field("id"), name = r.Field("name"), age = r.Field("age") }).ToList(); } 

在DataGridView中显示数据

你提到过:

要添加到网格,我遍历列表并为每个成员添加一行:

 for (int i = 0; i < members.Count; i++) { memberGrid.Rows.Add(new object[] ... 

当您将数据加载到DataTable (或甚至在List )时,您不需要DataGridViewDataGridView添加行,只需将数据分配给DataGridView DataSource属性即可。

为此,您可以覆盖表单的OnLoad方法或处理Load事件并将数据加载到数据表中并将其设置为DataGridView数据源:

 DataTable dt; protected override void OnLoad(EventArgs e) { base.OnLoad(e); dt = LoadData(); dataGridView1.DataSource = dt; } 

注意:如果出于任何原因您希望从GetData返回List ,则代码将为:

 List members; protected override void OnLoad(EventArgs e) { base.OnLoad(e); members = LoadData(); dataGridView1.DataSource = members; } 

过滤数据

然后要过滤数据,就足以使用dt.DefaultView.RowFilter

 dt.DefaultView.RowFilter = string.Format("name = '{0}'", searchBox.Text); 

注意:如果出于任何原因,您希望拥有List并对其应用filter,则在加载并将列表保存在表单成员中之后,就像我在上面的部分中所做的那样,使用linq过滤数据:

 dataGridView1.DataSource = members.Where(x=>x.Name ==searchBox.Text).ToList(); 

Reza Aghaei解释了如何解决问题,但是如果将来有人需要另外一种方法来处理这些情况,我就是这样做的。

所以提到的问题是将(memberGrid.DataSource as DataTable).DefaultView.RowFilter = string.Format("name = '{0}'", searchBox.Text);

它可能发生的原因有两个。

  • 您未分配DataSource因此它is null
  • 您分配了除DataTable之外的其他类型的对象,然后您尝试将其“返回”到DataTable因此它返回null

对于完美流程,始终将数据绑定到数据源并通过它进行操作。 以下是我在datagridviews中的操作方法。

  • 首先,我尝试将数据直接加载到DataTable中

因此,如果您从SQL加载它,只需使用DataAdapter并填充DataTable

 using(SqlConnetion....) { con.Open(); using(SqlDataAdapter da ....) { DataTable dt = new DataTable(); da.Fill(dt); dataGridView.DataSource = dt; //I use this method often because every change i am doing is directly into database and then i just refresh dgv if i need it by loading data again. } } 

如果直接加载数据, DataTable由于某种原因很难(需要自己创建数据并用foreach填充它,但是列太多或类似的东西)或者你想操作代码中的DataTable而不是DataTable中的DataTable你可以使用List

所以简单地创建对象

 public class Car { public string Model { get; set; } public Color Color { get; set; } public string LicencePlate { get; set; } public doube HP { get; set; } public Car() { } } 

然后我们说我们需要从jsonString加载汽车我们做List myCars = JsonConverter.Deserialize>(stringFromWebForExample);

现在我们有了一个列表,我们可以操作但需要将它放入datagridview。 我们再次只能通过dataGridView.DataSource = myCars来实现它,但是当涉及到datagridview中的显示时, DataTableList更具function性,所以我所做的是使用以下代码将该列表转换为datatable:

 public static DataTable ConvertToDataTable(this IList data) { PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T)); DataTable table = new DataTable(); foreach (PropertyDescriptor prop in properties) table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType); foreach (T item in data) { DataRow row = table.NewRow(); foreach (PropertyDescriptor prop in properties) row[prop.Name] = prop.GetValue(item) ?? DBNull.Value; table.Rows.Add(row); } return table; } 

并只是调用它dataGridView.DataSource = myCars.ConvertToDataTable();

这是处理数据并在DataGridView显示它的两种实用方法