Как связать список с dataGridView?
Кажется, я бегаю кругами и делал это в последние часы.
Я хочу заполнить сетку данных из массива строк. Я читал, что это невозможно напрямую, и что мне нужно создать пользовательский тип, который содержит строку как открытое свойство. Итак, я сделал класс:
public class FileName
{
private string _value;
public FileName(string pValue)
{
_value = pValue;
}
public string Value
{
get
{
return _value;
}
set { _value = value; }
}
}
это класс контейнера, и он просто имеет свойство со значением строки. Все, что я хочу сейчас - это чтобы эта строка появлялась в сетке данных, когда я связываю ее источник данных со списком.
Также у меня есть этот метод, BindGrid(), которым я хочу заполнить представление данных. Вот:
private void BindGrid()
{
gvFilesOnServer.AutoGenerateColumns = false;
//create the column programatically
DataGridViewTextBoxColumn colFileName = new DataGridViewTextBoxColumn();
DataGridViewCell cell = new DataGridViewTextBoxCell();
colFileName.CellTemplate = cell; colFileName.Name = "Value";
colFileName.HeaderText = "File Name";
colFileName.ValueType = typeof(FileName);
//add the column to the datagridview
gvFilesOnServer.Columns.Add(colFileName);
//fill the string array
string[] filelist = GetFileListOnWebServer();
//try making a List<FileName> from that array
List<FileName> filenamesList = new List<FileName>(filelist.Length);
for (int i = 0; i < filelist.Length; i++)
{
filenamesList.Add(new FileName(filelist[i].ToString()));
}
//try making a bindingsource
BindingSource bs = new BindingSource();
bs.DataSource = typeof(FileName);
foreach (FileName fn in filenamesList)
{
bs.Add(fn);
}
gvFilesOnServer.DataSource = bs;
}
Наконец, проблема: массив строк заполняется нормально, список создается нормально, но я получаю пустой столбец в представлении данных. Я также попробовал datasource = List<> напрямую, а не = bindingsource, но ничего не получилось.
Буду очень признателен за совет, это сводит меня с ума.
Ответы
Ответ 1
Используйте BindingList и установите DataPropertyName -Property столбца.
Попробуйте следующее:
...
private void BindGrid()
{
gvFilesOnServer.AutoGenerateColumns = false;
//create the column programatically
DataGridViewCell cell = new DataGridViewTextBoxCell();
DataGridViewTextBoxColumn colFileName = new DataGridViewTextBoxColumn()
{
CellTemplate = cell,
Name = "Value",
HeaderText = "File Name",
DataPropertyName = "Value" // Tell the column which property of FileName it should use
};
gvFilesOnServer.Columns.Add(colFileName);
var filelist = GetFileListOnWebServer().ToList();
var filenamesList = new BindingList<FileName>(filelist); // <-- BindingList
//Bind BindingList directly to the DataGrid, no need of BindingSource
gvFilesOnServer.DataSource = filenamesList
}
Ответ 2
может быть немного запоздалым, но полезным для будущего. если вам не требуется устанавливать пользовательские свойства ячейки и учитывать только текст заголовка и значение ячейки, то этот код поможет вам
public class FileName
{
[DisplayName("File Name")]
public string FileName {get;set;}
[DisplayName("Value")]
public string Value {get;set;}
}
а затем вы можете связать List как источник данных как
private void BindGrid()
{
var filelist = GetFileListOnWebServer().ToList();
gvFilesOnServer.DataSource = filelist.ToArray();
}
для получения дополнительной информации вы можете посетить эту страницу Привязать список объектов класса как Datasource к DataGridView
надеюсь, что это поможет вам.
Ответ 3
Я знаю, что это старо, но это немного задержало меня. Свойства объекта в вашем списке должны быть действительными "свойствами", а не только публичными членами.
public class FileName
{
public string ThisFieldWorks {get;set;}
public string ThisFieldDoesNot;
}
Ответ 4
Вместо создания нового класса контейнера вы можете использовать dataTable.
DataTable dt = new DataTable();
dt.Columns.Add("My first column Name");
dt.Rows.Add(new object[] { "Item 1" });
dt.Rows.Add(new object[] { "Item number 2" });
dt.Rows.Add(new object[] { "Item number three" });
myDataGridView.DataSource = dt;
Подробнее об этой проблеме вы можете найти здесь: http://psworld.pl/Programming/BindingListOfString
Ответ 5
Использование DataTable действует как указано пользователем927524.
Вы также можете сделать это, добавив строки вручную, что не потребует добавления определенного класса упаковки:
List<string> filenamesList = ...;
foreach(string filename in filenamesList)
gvFilesOnServer.Rows.Add(new object[]{filename});
В любом случае, спасибо user927524 за устранение этого странного поведения!