我已经设置了一个文本框来在我的数据网格上搜索名称,但我收到错误:“对象引用未设置为对象的实例。”
List<Member> members = new List<Member>();
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 选择中的每一行数据添加到列表中的方式。
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
});
}
最佳答案
因为你没有设置 DataSource
的 DataGridView
并且它为 null,那么当您在此语句中使用它时收到异常:(memberGrid.DataSource as DataTable).DefaultView...
.
而不是将行一一添加到 DataGridView
, 将数据分配给它的 DataSource
.然后根据您使用的数据结构,您可以过滤数据。
您可以使用以下任一解决方案:
作为一个选项,要解决这个问题,您可以将数据加载到
DataTable
中。并将其设置为DataSource
的DataGridView
.然后可以按照您尝试的方式进行过滤。此外,如果出于任何原因您更喜欢
List<Member>
并在加载数据并转换为List<Member>
后对其应用过滤器, 将列表保存在表单成员字段中,如List<Member> members;
然后使用linq
进行过滤:dataGridView1.DataSource = members.Where(x=>x.Name ==searchBox.Text).ToList();
有关详细信息,请阅读帖子中的以下部分。
为什么我收到 NullReferenceException
下面的代码行将抛出 NullReferenceException
如果DataSource
为空或 DataSource
不是 DataTable
:
(memberGrid.DataSource as DataTable).DefaultView.RowFilter = ...
在你的例子中,你通过添加行来填充数据库并且没有使用它的数据源,所以 DataSource
为空,上面的代码抛出异常。
查找有关如何调试的更多信息NullReferenceException
,看看What is a NullReferenceException, and how do I fix it? .
加载数据
您提到:
This is how I add each row of data from my SQL select into the list.
members.Add(new Member { id = Convert.ToInt32(reader["id"]), name = reader["name"].ToString(), ...
看来您正在使用 SQL 查询和 SqlDataReader
.那么你不需要使用 List<Member>
, 一个 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<Member>
,重构您的代码以返回 List<Member>
在 GetData
:
public List<Member> 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<int>("id"),
name = r.Field<string>("name"),
age = r.Field<int>("age")
}).ToList();
}
在 DataGridView 中显示数据
您提到:
To add to the grid, I loop through the list and add a row per member:
for (int i = 0; i < members.Count; i++) { memberGrid.Rows.Add(new object[] ...
当您将数据加载到 DataTable
中时(甚至在 List<Member>
中)您不需要将行一一添加到 DataGridView
中, 只需将数据分配给 DataSource
DataGridView
的属性(property).
为此,您可以覆盖 OnLoad
表格或句柄的方法 Load
事件并将数据加载到数据表中并将其设置为DataGridView
的数据源:
DataTable dt;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
dt = LoadData();
dataGridView1.DataSource = dt;
}
注意:如果出于任何原因您希望返回 List<Member>
来自 GetData
,代码将是:
List<Member> 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<Member>
并对其应用过滤器,在加载列表并将列表保存在表单成员中,就像我在上面部分所做的那样,使用 linq
过滤数据:
dataGridView1.DataSource = members.Where(x=>x.Name ==searchBox.Text).ToList();
关于c# - 使用搜索文本框 : 'Object reference not set to an instance of an object.' 中的值过滤数据 GridView 列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52237243/