C# 如何将 List<string> 绑定到 DataGridView 控件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/479329/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 05:00:34  来源:igfitidea点击:

How to bind a List<string> to a DataGridView control?

c#bindingdatagridview

提问by agnieszka

I have a simple List<string>and I'd like it to be displayed in a DataGridViewcolumn.
If the list would contain more complex objects, simply would establish the list as the value of its DataSourceproperty.

我有一个简单的List<string>,我希望它显示在一个DataGridView列中。
如果列表将包含更复杂的对象,只需将列表建立为其DataSource属性的值。

But when doing this:

但是当这样做时:

myDataGridView.DataSource = myStringList;

I get a column called Lengthand the strings' lengths are displayed.

我得到一个名为的列,Length并显示字符串的长度。

How to display the actual string values from the list in a column?

如何在列中显示列表中的实际字符串值?

采纳答案by sinm

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

那是因为 DataGridView 查找包含对象的属性。对于字符串,只有一个属性——长度。所以,你需要一个像这样的字符串的包装器

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

然后将List<StringValue>对象绑定到您的网格。有用

回答by Jarek Kardas

you can also use linq and anonymous types to achieve the same result with much less code as described here.

您还可以使用 linq 和匿名类型以更少的代码实现相同的结果,如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.

(..) 表中显示的值表示字符串的长度而不是字符串值 (!) 这可能看起来很奇怪,但这就是默认绑定机制的工作方式——给定一个对象,它将尝试绑定到该对象的第一个属性对象(它可以找到的第一个属性)。当传递一个实例时,它绑定到的 String 类的属性是 String.Length,因为没有其他属性可以提供实际的字符串本身。

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).

我们可以通过使用 LINQ 和匿名类型来改进这个解决方案——我们将使用 LINQ 查询来创建一个新的字符串包装器列表(在我们的例子中,字符串包装器将是一个匿名类型)。

 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:

我们要做的最后一个更改是将 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();
     }

This way we can reuse the code by calling single method on any collection of strings:

这样我们就可以通过在任何字符串集合上调用单个方法来重用代码:

Table1.SetDataBinding(testData.CreateStringWrapperForBinding());

回答by Tamanna Jain

Try this:

尝试这个:

IList<String> list_string= new List<String>();
DataGridView.DataSource = list_string.Select(x => new { Value = x }).ToList();
dgvSelectedNode.Show();

I hope this helps.

我希望这有帮助。

回答by jamisonLikeCode

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.

只要您绑定到实现 IEnumerable<string> 的任何内容,以下内容就应该有效。它会将列直接绑定到字符串本身,而不是绑定到该字符串对象的属性路径。

<sdk:DataGridTextColumn Binding="{Binding}" />

回答by user1246920

This is common issue, another way is to use DataTable object

这是常见问题,另一种方法是使用 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" });

This problem is described in detail here: http://www.psworld.pl/Programming/BindingListOfString

这个问题在这里有详细描述:http: //www.psworld.pl/Programming/BindingListOfString

回答by Sudeep

An alternate is to use a new helper function which will take values from List and update in the DataGridView as following:

另一种方法是使用一个新的辅助函数,它将从 List 中获取值并在 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;
    }

Then we can call this function the following way:

然后我们可以通过以下方式调用这个函数:

    DisplayStringListInDataGrid(<nameOfListWithStrings>, ref <nameOfDataGridViewToDisplay>, <nameToBeGivenForTheNewColumn>);

回答by user3042599

You might run into performance issues when assigning really large lists through LINQ. Following solution is suitable for large lists and without subclassing String:

通过 LINQ 分配非常大的列表时,您可能会遇到性能问题。以下解决方案适用于大型列表且无需子类化 String:

Set DataGridView (here "View") to virtual mode, create column you need and override / register for event CellValueNeeded

将 DataGridView(此处为“View”)设置为虚拟模式,创建您需要的列并覆盖/注册事件 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:

那么您可以简单地将您的列表分配给 DataGridView:

List<String> MyList = ...
View.DataSource = MyList;

回答by Neojt

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);
}