使用搜索文本框中的值过滤数据网格视图列表:“对象引用未设置为对象的实例。” [英] Filter data grid view list with the value from the search text box: 'Object reference not set to an instance of an object.'

查看:48
本文介绍了使用搜索文本框中的值过滤数据网格视图列表:“对象引用未设置为对象的实例。”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have set up a text box to search names on my data grid but I am receiving the error: 'Object reference not set to an instance of an object.'

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 更改为列表成员。我也尝试过在 DataTable 前面使用 List / Member 进行强制转换,但这似乎不起作用。

I have attempted to change DataTable to List or Member. I have also tried casting using List/Member in front of DataTable but it doesn't seem to work.

什么是最好的方法?

编辑:

这是我将SQL选择中的每一行数据添加到列表中的方式。

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(),
    age = Convert.ToInt32(reader["age"]),
    image_url = (Image)Properties.Resources.ResourceManager.GetObject(reader["image_url"].ToString())
});

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

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[]
    {
        members[i].image_url,
        members[i].name,
        members[i].age
    });
}


推荐答案

由于您未设置 DataSource DataGridView ,它为空,然后在此语句中使用它时收到异常:(memberGrid.DataSource作为DataTable)。DefaultView...

Since you didn't set DataSource of DataGridView and it's null, then you received an exception when you used it in this statement: (memberGrid.DataSource as DataTable).DefaultView....

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

Instead of adding rows one by one to the DataGridView, assign data to its DataSource. Then depending to the data structure which you are using, you can filter data.

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

You can use either of the following solutions:


  • 作为解决此问题的选项,您可以将数据加载到 DataTable 中并将其设置为<$ DataGridView 的c $ c> DataSource 。然后可以按照您尝试的方式进行过滤。

  • As an option, to fix the problem, you can load data into a DataTable and set it as DataSource of the DataGridView. Then the filtering can be done the same way that you are trying to do.

如果出于某种原因,您更喜欢使用 List< Member> 并对其进行过滤,在加载数据并转换为 List< Member> 之后,将列表保留在表单成员字段中像 List< Member>成员; 然后使用 linq 进行过滤:

Also if for any reason you prefer to have a List<Member> and apply filter on that, after loading data and converting to a List<Member>, keep the list in a form member field like List<Member> members; then for filtering using linq:

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


有关更多详细信息,请阅读

For more details read the following sections in the post.

为什么我收到NullReferenceException

下面的代码行会抛出 NullReferenceException 如果 DataSource 为空或 DataSource 不是 DataTable

The following line of code will throw a NullReferenceException if DataSource is null or DataSource is not a DataTable:

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

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

In your case, You are filling the database by adding rows and didn't used its data source, so DataSource is null and above code throws exception.

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

To find more information about how to debug NullReferenceException, take a look at What is a NullReferenceException, and how do I fix it?.

加载数据

您已提及:


这是我将SQL选择中的每一行数据添加到列表中的方式。

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 就足够了。您可以将代码更改为以下代码以加载数据:

It seems you are using a SQL query and a SqlDataReader. Then you don't need to use a List<Member>, a DataTable would be enough for you. You can change your code to the following code to load data:

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> ,重构代码以在<$ c $中返回 List< Member> c> GetData :

Note: If for any reason you are interested to keep working with List<Member>, refactor your code to return a List<Member> in 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 ,只需将数据分配给<$ c $的 DataSource 属性c> DataGridView 。

When you load data into a DataTable (or even in a List<Member>) you don't need to add rows one by one to the DataGridView, just assign the data to DataSource property of the DataGridView.

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

To do so, you can override OnLoad method of the form or handle Load event and load data into a data table and set it as data source of the DataGridView:

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

注意:如果出于某种原因您更愿意返回来自 GetData List< Member> ,代码将为:

Note: If for any reason you preferred returning a List<Member> from GetData, the code will be:

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

过滤数据

然后过滤数据,使用 dt.DefaultView.RowFilter 就足够了:

Then to filter data, it's enough to use dt.DefaultView.RowFilter:

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

注意:如果出于某种原因,您更愿意使用 List< Member> 并对其应用过滤器,在加载列表并将其保留在表单成员中后,就像我在上一节中所做的那样,请使用 linq 来过滤数据:

Note: If for any reason you prefer to have a List<Member> and apply filter on that, after loading and keep the list in a form member like what I did in above sections, use linq to filter data:

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

这篇关于使用搜索文本框中的值过滤数据网格视图列表:“对象引用未设置为对象的实例。”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆