使用搜索文本框中的值过滤数据网格视图列表:’对象引用未设置为对象的实例。
我已经设置了一个文本框来搜索我的数据网格上的名称,但是我收到错误: '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
更改为List
或Member
。 我也尝试使用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...
而不是DataGridView
向DataGridView
添加行,而是将数据分配给其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
。 那么你不需要使用List
, DataTable
就足够了。 您可以将代码更改为以下代码以加载数据:
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
,请重构您的代码以返回GetData
的List
:
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
)时,您不需要DataGridView
向DataGridView
添加行,只需将数据分配给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
现在我们有了一个列表,我们可以操作但需要将它放入datagridview。 我们再次只能通过dataGridView.DataSource = myCars
来实现它,但是当涉及到datagridview中的显示时, DataTable
比List
更具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
显示它的两种实用方法