【问题标题】:List to Datatable. Datatable doesn't show any values列表到数据表。数据表不显示任何值
【发布时间】:2013-11-10 14:20:41
【问题描述】:

我正在尝试制作一个“历史页面”。读取用户作为字符串的 url 并将其添加到 List 并将其转换为 DataTable 但是当我单击显示历史菜单选项时,我得到的只是列“urls”和它下面的一个空单元格。我假设我也可能不恰当地使用了 Add 方法。

主窗体类:

private void showHistoryToolStripMenuItem_Click(object sender, EventArgs e)
{
   using (History history = new History())
   {
      history.ShowDialog();
      nonHomepage = URLInput.Text;
      if (String.IsNullOrEmpty(nonHomepage))
      {
         return;
      }
      else
      {
         addToList(nonHomepage);
      }
   }
}

public void addToList(string URLvalue)
{
   listH.Add(URLvalue);
}

public List<string> getList()
{
   return listH;
}

历史表单类:

private void History_Load(object sender, EventArgs e)
{
   Form1 br = new Form1();
   list = br.listH;
   DataTable table = ConvertListToDataTable(list);
   dataGridView1.DataSource = table;
}

static DataTable ConvertListToDataTable(List<string> l)
{
   DataTable table = new DataTable();
   //int columns = 0;
   table.Columns.Add("urls");
   foreach(string s in l)
   {
      table.Rows.Add(s);
   }
   return table;
}

有什么建议吗?如果我将所有这些 url 放入文件中,然后从文件中读取并写入文本框/表格会怎样?或者也许我应该改变数据结构?例如,去查字典?提前致谢。

【问题讨论】:

  • 我猜你还没有调试过这段代码。因为我认为问题在于您在表单之间传递列表时。更具体地说,这个位:Form1 br = new Form1(); list = br.listH;... 如果您重新实例化该类,它的所有变量都将设置为其默认值(并且列表为空)。
  • 是的,它可以编译。我是否应该将主表单中的 url 字符串传递给历史表单,然后在历史表单中列出?
  • 你应该开始添加Dataset.Extentions引用,这样你就可以直接在DataTable对象上使用linq并转换成一个列表

标签: c# winforms list datatable


【解决方案1】:

当你添加表格行时,实际上你必须添加一行,而不仅仅是一个字符串。

    foreach(string s in l)
    {
        var row = table.NewRow();
        row[0] = s;
        table.Rows.Add(row);
    }
    return table;

另外,添加断点并确保您的列表在转换之前不为空,并确保之后正确填充您的表格。


此外,从架构的角度来看,如果您只有一列信息,那么您实际上不应该使用DataTableList&lt;T&gt; 就足够了。您在这里使用DataTable 是否有某些原因?

【讨论】:

  • 其实他可以靠字符串填充行(如果列是字符串类型,默认是什么情况,他的DataTable填充部分没问题)。
  • 我是 C# 新手,目前正在使用不同的数据结构来寻找更适合并快速安静地存储和搜索历史页面的数据结构。可能会为收藏夹页面使用相同的列表。我还没有写任何线程,所以我的程序真的很慢。
【解决方案2】:

SpikeX 答案的替代语法:

 int i = 0;
 foreach (string s in l)
 {
      table.Rows.Add()
      tables.Rows[i].SetField("COLUMN NAME", s);
      i++
 }

我想您的表中只有 1 列,因此使用 SetField 可能有点过分。但是当您有多个列时,它会更容易阅读,而不必返回并检查哪个列具有哪个索引。

【讨论】:

  • 当您尝试任一变体时会发生什么?
【解决方案3】:

您的问题是您在private void History_Load(object sender, EventArgs e) 中创建一个空的Form1 并将listH(它是空的)传递给方法ConvertListToDataTable(list),因此您有空网格。解决方案是您必须更改 History 初始化或显式调用某些方法 LoadData 来加载实际列表,如下所示:

解决方案 1

public partial class History : Form {
  public History(){
    InitializeComponent();
  }
  public Form1 MainForm {get;set;}
  private void History_Load(object sender, EventArgs e) {     
    var list = MainForm == null ? new List<string>() : MainForm.listH;
    DataTable table = ConvertListToDataTable(list);
    dataGridView1.DataSource = table;
  }
  //other code ....
}
//Form1 class
private void showHistoryToolStripMenuItem_Click(object sender, EventArgs e) {
  //note the MainForm initialization using Property initializer
  using (History history = new History {MainForm = this}) {
    history.ShowDialog();
    nonHomepage = URLInput.Text;
    if (String.IsNullOrEmpty(nonHomepage)) {
      return;
    } else {
      addToList(nonHomepage);
    }
  }
}

解决方案 2

//History class
public partial class History : Form {
  //define this method to call explicitly before showing your History dialog
  public void LoadData(List<string> list){
    DataTable table = ConvertListToDataTable(list);
    dataGridView1.DataSource = table;
  }
  //other code ...
}
//Form1 (or Main Form) class
private void showHistoryToolStripMenuItem_Click(object sender, EventArgs e) {
  using (History history = new History()) {
     history.LoadData(listH);// <---- call this first to load data
     history.ShowDialog();
     nonHomepage = URLInput.Text;
     if (String.IsNullOrEmpty(nonHomepage)) {
       return;
     } else {
       addToList(nonHomepage);
     }
  }
}

【讨论】:

  • 感谢@KingKing,它现在可以工作,但我可能需要将 url 保存到单独的文件中,以便它记住上一个会话。你认为它方便还是会减慢我的程序?我的意思是一直从文件中读取和写入。
  • @Messerschmitt 如果文件不是太大,我认为没关系。即使文件有很多行,您也可以随时使用threading 在后台打开和加载它。但是我不认为这是你的情况,所以我们可以正常加载它。
  • 谢谢。还有一个问题(我希望我没有要求太多)。当用户双击带有 url 的行时,我为事件编写了一些代码,以便将 url 作为字符串传递回主窗体并在那里加载。但是,这样做时我得到了这个 ArgumentOutOfRangeException: form.pageInput.Text = dataGridView1.SelectedRows[0].ToString();无法弄清楚我在这里做错了什么。是不是因为它更像一个集合而不是一个字符串?
  • @Messerschmitt SelectedRows 仅在您将SelectionMode 设置为FullRowSelect可用,否则它始终为空除非您明确选择点击行标题
  • 我刚刚检查过,它最初设置为行标题。所以我将其更改为 FullRowSelect 并且仍然得到相同的错误。但是,如果我最后没有指定索引: form.pageInput.Text = dataGridView1.SelectedRows.ToString();它转到加载页面并在那里提示错误的方法。这意味着字符串为空:(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-21
  • 2015-12-15
  • 2021-05-08
  • 2011-12-08
相关资源
最近更新 更多