c# - 使用搜索文本框 : 'Object reference not set to an instance of an object.' 中的值过滤数据 GridView 列表

标签 c# .net winforms datagridview datasource

我已经设置了一个文本框来在我的数据网格上搜索名称,但我收到错误:“对象引用未设置为对象的实例。”

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 更改为 ListMember。我也尝试过在 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
    });
}

最佳答案

因为你没有设置 DataSourceDataGridView并且它为 null,那么当您在此语句中使用它时收到异常:(memberGrid.DataSource as DataTable).DefaultView... .

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

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

  • 作为一个选项,要解决这个问题,您可以将数据加载到 DataTable 中。并将其设置为 DataSourceDataGridView .然后可以按照您尝试的方式进行过滤。

  • 此外,如果出于任何原因您更喜欢 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/

相关文章:

c# - 为什么 Regex.Match 没有 GetEnumerator 函数?

c# - 使用 MVVM WPF 将数据保存到 Collection 和 Display

c# - 使用依赖注入(inject)替换 ASP.NET Core 中的 JWT Bearer Options

c# - Linq 计数与 IList 计数

c# - 列表列表的组合,使每个组合都有唯一的元素

.net - 视觉 C++.net : Disappearing project

c# - TDD : Is it plausible to have integration tests, 但没有单元测试?

C# 控件超出父边界?

c# - 在 C# 中对 TextBox 实现输入限制的最佳方法是什么?

c# - Async 和 Await 命令编译没有错误,但不会让我的 Windows 窗体响应