Поскольку вы не установили 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
имеет значение null и код генерирует исключение.
Для получения дополнительной информации о том, как отладить NullReferenceException
, взгляните на Что такое исключение NullReferenceException и как его исправить? .
Загрузка данных
Вы упомянули:
Так я добавляю в список каждую строку данных из моего SQL-выбора.
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>
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
Вы упомянули:
Чтобы добавить в сетку, я перебираю список и добавляю строку для каждого члена:
for (int i = 0; i < members.Count; i++) {
memberGrid.Rows.Add(new object[]
...
Когда вы загружаете данные в DataTable
(или даже в List<Member>
), вам не нужно добавлять строки одну за другой к DataGridView
, просто присвойте данные свойству DataSource
свойства DataGridView
.
Для этого вы можете переопределить метод 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();