【问题标题】:How to bind a List<string> to a DataGridView control?如何将 List<string> 绑定到 DataGridView 控件?
【发布时间】:2010-10-03 12:29:46
【问题描述】:

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

但是当这样做时:

myDataGridView.DataSource = myStringList;

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

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

【问题讨论】:

    标签: c# binding datagridview


    【解决方案1】:

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

    public class StringValue
    {
        public StringValue(string s)
        {
            _value = s;
        }
        public string Value { get { return _value; } set { _value = value; } }
        string _value;
    }
    

    然后将List&lt;StringValue&gt; 对象绑定到您的网格。有效

    【讨论】:

    • 列的DataPropertyName必须是Value
    • 分组呢?现在“A”不等于“A”,我有两组“A”。
    【解决方案2】:

    您还可以使用 linq 和匿名类型以更少的代码实现相同的结果,如 here 所述。

    更新:博客已关闭,这是内容:

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

    这意味着要获得正确的绑定,我们需要一个包装器对象,它将字符串的实际值作为属性公开:

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

    【讨论】:

      【解决方案3】:

      试试这个:

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

      我希望这会有所帮助。

      【讨论】:

      • 如果您使用 List 而不是 IList,您可以使用 List.ConvertAll(x =&gt; new { Value = x});
      • 这可行,但对 list_string 的更改不会更新 DataGridView。
      • 更新 Grid 需要再次运行 linq 语句。
      • 什么是 dgvSelectedNode.Show() ?
      【解决方案4】:

      只要您绑定到任何实现 IEnumerable 的东西,以下内容应该可以工作。它将列直接绑定到字符串本身,而不是绑定到该字符串对象的属性路径。

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

      【讨论】:

      • 我已经测试了这个建议并且它工作正常。它比其他解决方案更清洁。
      • 这不是silverlight特有的吗?
      • 这也适用于 WPF.. 你为什么要对不正确的评论投赞成票?
      • 拒绝投票,因为原始问题有“datagridview”标签,这是winforms控件。此解决方案不适用于 winfroms。
      【解决方案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

      【讨论】:

      • 但是datatable比List重,大部分开发者会避免使用datatable。
      【解决方案6】:

      另一种方法是使用一个新的辅助函数,该函数将从 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;
          }
      

      那么我们可以这样调用这个函数:

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

      【讨论】:

        【解决方案7】:

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

        将 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】:

          试试这个:

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

          【讨论】:

          • 你意识到这个问题已经有 6 年的历史了,并且已经得到了回答,对吗?
          • 您必须先将列添加到数据网格视图,否则这将不起作用
          猜你喜欢
          • 1970-01-01
          • 2013-04-15
          • 1970-01-01
          • 2011-02-10
          • 1970-01-01
          • 2013-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-28
          相关资源
          最近更新 更多