Как связать List <string> с элементом управления DataGridView?
У меня есть простой List<string>
, и я бы хотел, чтобы он отображался в столбце DataGridView
.
Если список будет содержать более сложные объекты, он просто установит список как значение его свойства DataSource
.
Но при этом:
myDataGridView.DataSource = myStringList;
Я получаю столбец с именем Length
и отображаются длины строк.
Как отобразить фактические строковые значения из списка в столбце?
Ответы
Ответ 1
Это потому, что DataGridView ищет свойства содержащихся объектов. Для строки есть только одно свойство - длина. Итак, вам нужна оболочка для строки, подобной этой
public class StringValue
{
public StringValue(string s)
{
_value = s;
}
public string Value { get { return _value; } set { _value = value; } }
string _value;
}
Затем привяжите объект List<StringValue>
к вашей сетке. Он работает
Ответ 2
Попробуйте следующее:
IList<String> list_string= new List<String>();
DataGridView.DataSource = list_string.Select(x => new { Value = x }).ToList();
dgvSelectedNode.Show();
Надеюсь, это поможет.
Ответ 3
Следующее должно работать до тех пор, пока вы привязаны ко всему, что реализует IEnumerable <string> . Он привяжет столбец непосредственно к самой строке, а не к пути свойства этого строкового объекта.
<sdk:DataGridTextColumn Binding="{Binding}" />
Ответ 4
вы также можете использовать linq и анонимные типы для достижения того же результата с гораздо меньшим количеством кода, как описано здесь.
UPDATE: блог отключен, здесь содержимое:
(..) Значения, указанные в таблице, представляют длину строк вместо строковых значений (!)
Это может показаться странным, но это то, как механизм привязки работает по умолчанию - с учетом объекта он попытается связать с первым свойством этого объекта (первое свойство, которое он может найти).
Когда передан экземпляр класса String, к которому он привязан, является String.Length, так как theres не имеет другого свойства, которое предоставило бы собственно строку.
Это означает, что для получения нашего права привязки нам нужен объект-оболочка, который будет показывать фактическое значение строки в качестве свойства:
public class StringWrapper
{
string stringValue;
public string StringValue { get { return stringValue; } set { stringValue = value; } }
public StringWrapper(string s)
{
StringValue = s;
}
}
List<StringWrapper> testData = new List<StringWrapper>();
// add data to the list / convert list of strings to list of string wrappers
Table1.SetDataBinding(testdata);
Хотя это решение работает так, как ожидалось, ему требуется довольно много строк кода (в основном для преобразования списка строк в список оберток строк).
Мы можем улучшить это решение, используя LINQ и анонимные типы - используйте LINQ-запрос для создания нового списка оберток строк (в нашем случае строковая оболочка будет анонимным).
var values = from data in testData select new { Value = data };
Table1.SetDataBinding(values.ToList());
Последнее изменение должно было состоять в том, чтобы переместить код LINQ в метод расширения:
public static class StringExtensions
{
public static IEnumerable CreateStringWrapperForBinding(this IEnumerable<string> strings)
{
var values = from data in strings
select new { Value = data };
return values.ToList();
}
Таким образом, мы можем повторно использовать код, вызывая один метод для любого набора строк:
Table1.SetDataBinding(testData.CreateStringWrapperForBinding());
Ответ 5
Это обычная проблема, другой способ - использовать объект DataTable
DataTable dt = new DataTable();
dt.Columns.Add("column name");
dt.Rows.Add(new object[] { "Item 1" });
dt.Rows.Add(new object[] { "Item 2" });
dt.Rows.Add(new object[] { "Item 3" });
Эта проблема подробно описана здесь: http://www.psworld.pl/Programming/BindingListOfString
Ответ 6
Попробуйте следующее:
//i have a
List<string> g_list = new List<string>();
//i put manually the values... (for this example)
g_list.Add("aaa");
g_list.Add("bbb");
g_list.Add("ccc");
//for each string add a row in dataGridView and put the l_str value...
foreach (string l_str in g_list)
{
dataGridView1.Rows.Add(l_str);
}
Ответ 7
Вы можете столкнуться с проблемами производительности при назначении действительно больших списков через LINQ.
Следующее решение подходит для больших списков и без подкласса String:
Установите DataGridView (здесь "Вид" ) в виртуальный режим, создайте нужный столбец и переопределите/зарегистрируйтесь для события CellValueNeeded
private void View_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
{
// Optionally: check for column index if you got more columns
e.Value = View.Rows[e.RowIndex].DataBoundItem.ToString();
}
то вы можете просто назначить свой список DataGridView:
List<String> MyList = ...
View.DataSource = MyList;
Ответ 8
Альтернативой является использование новой вспомогательной функции, которая будет принимать значения из списка и обновления в DataGridView следующим образом:
private void DisplayStringListInDataGrid(List<string> passedList, ref DataGridView gridToUpdate, string newColumnHeader)
{
DataTable gridData = new DataTable();
gridData.Columns.Add(newColumnHeader);
foreach (string listItem in passedList)
{
gridData.Rows.Add(listItem);
}
BindingSource gridDataBinder = new BindingSource();
gridDataBinder.DataSource = gridData;
dgDataBeingProcessed.DataSource = gridDataBinder;
}
Затем эту функцию можно вызвать следующим образом:
DisplayStringListInDataGrid(<nameOfListWithStrings>, ref <nameOfDataGridViewToDisplay>, <nameToBeGivenForTheNewColumn>);