Reputation: 15345
I have a simple List<string>
and I'd like it to be displayed in a DataGridView
column.
If the list would contain more complex objects, simply would establish the list as the value of its DataSource
property.
But when doing this:
myDataGridView.DataSource = myStringList;
I get a column called Length
and the strings' lengths are displayed.
How to display the actual string values from the list in a column?
Upvotes: 93
Views: 164956
Reputation: 1069
Try this:
IList<String> list_string= new List<String>();
DataGridView.DataSource = list_string.Select(x => new { Value = x }).ToList();
dgvSelectedNode.Show();
Upvotes: 106
Reputation: 29
Try this :
//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);
}
Upvotes: 2
Reputation: 517
You might run into performance issues when assigning really large lists through LINQ. Following solution is suitable for large lists and without subclassing String:
Set DataGridView (here "View") to virtual mode, create column you need and override / register for event 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();
}
then you can simply assign your list to DataGridView:
List<String> MyList = ...
View.DataSource = MyList;
Upvotes: 2
Reputation: 41
An alternate is to use a new helper function which will take values from List and update in the DataGridView as following:
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;
}
Then we can call this function the following way:
DisplayStringListInDataGrid(<nameOfListWithStrings>, ref <nameOfDataGridViewToDisplay>, <nameToBeGivenForTheNewColumn>);
Upvotes: 0
Reputation: 1377
Thats because DataGridView looks for properties of containing objects. For string there is just one property - length. So, you need a wrapper for a string like this
public class StringValue
{
public StringValue(string s)
{
_value = s;
}
public string Value { get { return _value; } set { _value = value; } }
string _value;
}
Then bind List<StringValue>
object to your grid. It works
Upvotes: 75
Reputation: 8455
you can also use linq and anonymous types to achieve the same result with much less code as described here.
UPDATE: blog is down, here's the content:
(..) The values shown in the table represent the length of strings instead of string values (!) It may seem strange, but that’s how binding mechanism works by default – given an object it will try to bind to the first property of that object (the first property it can find). When passed an instance the String class the property it binds to is String.Length since there’s no other property that would provide the actual string itself.
That means that to get our binding right we need a wrapper object that will expose the actual value of a string as a property:
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);
While this solution works as expected it requires quite a few lines of code (mostly to convert list of strings to the list of string wrappers).
We can improve this solution by using LINQ and anonymous types- we’ll use LINQ query to create a new list of string wrappers (string wrapper will be an anonymous type in our case).
var values = from data in testData select new { Value = data };
Table1.SetDataBinding(values.ToList());
The last change we’re going to make is to move the LINQ code to an extension method:
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();
}
This way we can reuse the code by calling single method on any collection of strings:
Table1.SetDataBinding(testData.CreateStringWrapperForBinding());
Upvotes: 13
Reputation: 81
This is common issue, another way is to use DataTable object
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" });
This problem is described in detail here: http://www.psworld.pl/Programming/BindingListOfString
Upvotes: 8
Reputation: 713
The following should work as long as you're bound to anything that implements IEnumerable<string>. It will bind the column directly to the string itself, rather than to a Property Path of that string object.
<sdk:DataGridTextColumn Binding="{Binding}" />
Upvotes: 19