【问题标题】:How can I bind my List<string> to a datagridView?如何将我的 List<string> 绑定到 datagridView?
【发布时间】:2013-04-15 10:17:29
【问题描述】:

我正在尝试使用以下代码在 datagridview 中显示列表的内容。

List<string> data = new List<string>(); 
dataGridView1.DataSource = data;  

我正在将我的数据添加到 backgroundWorker 的列表中。如果我将 List 更改为 BindingList,我会收到一条错误消息

Cross-thread operation not valid: Control 'dataGridView1' accessed from a thread other than the thread it was created on.

但是,如果我使用列表,当显示数据网格时,我会得到第三列,它只包含类别中每个条目的字符串的长度。

有谁知道在使用 BackgroundWorker 时如何让数据网格显示字符串内容而不是字符串长度?


    private void OnBackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
    {            
        importExcelFile();            
    }

    private void importExcelFile()
    {
        // hard coded file name for testing. 
        TextFieldParser parser = new TextFieldParser(@"E:\\test.csv");
        parser.TextFieldType = FieldType.Delimited;
        parser.SetDelimiters(",");

        while (!parser.EndOfData)
        {
            //Processing row
            string[] fields = parser.ReadFields();
            foreach (string field in fields)
            {
                //TODO: Process field
                data.Add(field);
            }
        }
        parser.Close();
    }

    private void loadFileToolStripMenuItem_Click(object sender, EventArgs e)
    {
        backgroundWorker1.DoWork += OnBackgroundWorkerDoWork;
        backgroundWorker1.RunWorkerAsync();
    }

    private void OnBackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        dataGridView1.DataSource = data;
    }

【问题讨论】:

  • 显示你的代码的其余部分,特别是你的 do work 方法以及你如何将列表传递给 BG 工作人员
  • 在分配给 DataSource 之前,您是否正在等待数据完成添加到 List 中?
  • 你需要将data从Bg工作线程中传递到这个函数中:private void loadFileToolStripMenuItem_Click。编译器为您提供所需的所有信息。看起来您正在工作线程中设置 datagridview 的一些属性。数据网格视图是在 UI 线程中定义的,您正试图从 后台工作线程 更新它。您可以使用委托或通过ProgressChangedRunWorkerCompleted 事件在线程之间传递数据
  • 我添加了 RunWorkerCompleted,但我仍然得到添加了字符串长度(不是内容)的第三列
  • @CocoaDev 是的,但是您没有将数据从 bg 工作线程中传递出去,是吗?您可以使用委托或上面列出的事件在线程之间传递数据。您可以使用以下内容访问数据:MyType obj = (MyType)sender;,并且您仍在访问 bg 工作线程中的 datagridview,这将导致跨线程问题...参考此行 dataGridView1.Columns[0].Name = "URL";。您需要在考虑线程安全的情况下重新考虑您的方法。

标签: c# list datagridview bindinglist


【解决方案1】:

您可以使用BackgroundWorker.ReportProgress 传递列表。我允许传递进度和自定义对象 (full dentition on MSDN)。处理这个事件是 UI 线程,所以它是正确的。

如果你最后需要这个,只需使用 RunWorkerCompletedEventArgs.Result (again definition on MSDN)

【讨论】:

  • 没有错误信息。我看不到 dataGridView 中列出的数据。我看到了字符串的长度(在这种情况下是 URL)
【解决方案2】:

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

我创建了一个类

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

然后将列表更改为列表

我正在获取数据,但它出现在第 3 列中。我只假设有 2 列。

【讨论】:

    【解决方案3】:

    请创建一个委托并使用control.Invoke调用委托

    您可以像这样使用 Invoke:

    private void AddToListBox(object oo)
    {
        Invoke(new MethodInvoker(delegate { listBox.Items.Add(oo); }));
    }
    

    更多关于Background Worker

    祝你好运!

    【讨论】:

    • 没有错误信息。我看不到 dataGridView 中列出的数据。我看到了字符串的长度(在这种情况下是 URL)
    • 在 UI 线程中创建的控件不能以正常方式在另一个线程中访问,所以你必须按照我说的 :)
    • 是的,只有在我使用 BindingList 时才会发生。我正在使用常规列表。我应该改用 BindingList 吗?如果是这样,那会有什么帮助?
    • 请记住,如果您使用 Background Worker,您应该只搜索 Invoke 和 BackgroundWorker - 我已经使用过很多次了 :)
    【解决方案4】:

    使用此代码。我也遇到过类似的问题,但使用 LinQ 解决了它。

    IList<String> listObj = new List<String>();
    dataGridView1.DataSource = listObj.Select(x => new { Value = x }).ToList();
    

    这里,

    dataGridView1 :- ID of datagridview
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-03
      • 1970-01-01
      • 2011-02-10
      • 2013-01-01
      • 1970-01-01
      • 2021-06-28
      • 2012-03-26
      • 1970-01-01
      相关资源
      最近更新 更多