C# 将 DataTable 绑定到现有 DataGridView 列定义
Posted
技术标签:
【中文标题】C# 将 DataTable 绑定到现有 DataGridView 列定义【英文标题】:C# Bind DataTable to Existing DataGridView Column Definitions 【发布时间】:2011-02-13 04:09:09 【问题描述】:我一直在与 NullReferenceException 作斗争,希望这里有人能够为我指明正确的方向。我正在尝试创建和填充 DataTable,然后在 DataGridView 控件中显示结果。基本代码如下,在我调用新的 UpdateResults_Delegate 时,执行以 NullReferenceException 停止。奇怪的是,在从 QueryEventEntries 返回条目之前,我可以成功地跟踪 entry.Rows.Count,因此我至少可以显示 1) 条目不是空引用,并且 2) DataTable 包含数据行。我知道我一定做错了什么,但我就是不知道是什么。
private void UpdateResults(DataTable entries)
dataGridView.DataSource = entries;
private void button_Click(object sender, EventArgs e)
PerformQuery();
private void PerformQuery()
DateTime start = new DateTime(dateTimePicker1.Value.Year,
dateTimePicker1.Value.Month,
dateTimePicker1.Value.Day,
0, 0, 0);
DateTime stop = new DateTime(dateTimePicker2.Value.Year,
dateTimePicker2.Value.Month,
dateTimePicker2.Value.Day,
0, 0, 0);
DataTable entries = QueryEventEntries(start, stop);
UpdateResults(entries);
private DataTable QueryEventEntries(DateTime start, DateTime stop)
DataTable entries = new DataTable();
entries.Columns.AddRange(new DataColumn[]
new DataColumn("event_type", typeof(Int32)),
new DataColumn("event_time", typeof(DateTime)),
new DataColumn("event_detail", typeof(String)));
using (SqlConnection conn = new SqlConnection(DSN))
using (SqlDataAdapter adapter = new SqlDataAdapter(
"SELECT event_type, event_time, event_detail FROM event_log " +
"WHERE event_time >= @start AND event_time <= @stop",
conn))
adapter.SelectCommand.Parameters.AddRange(new Object[]
new SqlParameter("@start", start),
new SqlParameter("@stop", stop));
adapter.Fill(entries);
return entries;
更新
我想总结并提供一些我从这里的讨论和调试工作中学到的额外信息,因为我最初发布了这个问题。
我正在重构从数据库中检索记录的旧代码,将这些记录收集为一个数组,然后遍历该数组以逐行填充 DataGridView。线程最初的实现是为了在不必要的循环期间补偿和保持 UI 响应。我已经剥离了线程/调用;现在一切都发生在同一个执行线程上(谢谢Sam)。
我正在尝试使用可以填充 DataAdapter 的 DataTable 来替换缓慢、笨拙的方法,并通过它的 DataSource 属性分配给 DataGridView(以上代码已更新)。
在将其分配为 DataGridView 的 DataSource 之前,我已经遍历条目 DataTable 的行以验证该表是否包含预期的数据。
foreach (DataRow row in entries.Rows)
System.Diagnostics.Trace.WriteLine(
String.Format("0 1 2", row[0], row[1], row[2]));
DataGridView 的列之一是自定义 DataGridViewColumn,用于对 event_type 值进行样式化。抱歉,我之前在原帖中没有提到这一点,但我不知道这对我的问题很重要。我已将此列暂时转换为标准 DataGridViewTextBoxColumn 控件,并且不再遇到异常。
DataTable 中的字段附加到已在 DataGridView 的设计视图中预先指定的字段列表中。记录的值被填充到这些附加字段中。当运行时尝试呈现单元格时,会提供一个空值(因为 应该呈现的值 已完成,因此会覆盖几列)。
鉴于此,我正在重新命名并重新标记问题。如果有经验的其他人可以指导我如何将 DataTable 绑定到 DataGridView 的现有列定义,我仍然会很感激。
【问题讨论】:
为什么要在单独的线程中读取数据库? 我试图重构的旧代码被编写为从数据库中读取结果,遍历它们以填充数组,然后返回数组...然后将其输入 UpdateResults然后遍历数组并逐行填充DataGridView。根据行数,这可能需要几秒钟,线程可能是保持 GUI 响应的方式。 您不应从非 UI 线程更新 UI 组件。我不明白这会如何导致 NRE,它应该是别的东西,但它可能是相关的。 我能够重新创建您发布的代码并且它在没有 NullReferenceException 的情况下工作。我认为问题与您在 cmets 中向 Sam 提到的自定义数据类型有关。您能给我们提供有关该自定义类型的更多信息吗?例如,构造函数或属性设置器有什么特别之处吗?另外,如果你不在单独的线程上调用,你会得到异常吗? 【参考方案1】:您需要确保每列的DataPropertyName
属性设置为DataColumn
的ColumnName
的对应名称。
您可能还需要将DataGridView
的AutoGenerateColumns
属性设置为false
。
我找到了解决方案here。
【讨论】:
【参考方案2】:如果错误发生在UpdateResults
内部,那么听起来dataGridView
为空。
private void UpdateResults(DataTable entries)
dataGridView.DataSource = entries; // when is dataGridView set?
【讨论】:
dataGridView 已设置并显示在表单上。我使用 Visual Studio 中的 UI 编辑器放置它,并命名它的列、格式等。 @Timothy,那么错误到底发生在哪一行?什么是完整的堆栈跟踪?您是否附加了调试器并单步执行以查看什么是 null? 我尝试在应用程序的其他地方以类似的方式重构代码,尽管我添加到 dataTable 的元素之一是自定义数据类型。 entry.Columns.Add("colCustType", typeof(CustDataType)); CustDataType ct = new CustDataType(); ct.Property = 结果.GetInt32(2); entry.Rows.Add(..., ct, ...);在这里,我在自定义 dgvCell 的绘制方法中进一步沿着执行路径获取 NRE。也许他们是相似的?第一个表中还有一个自定义 dgvCell,也许我无法正确识别由于线程而发生异常的位置? @Sam,时间不早了。我将尝试在明天晚上逐步完成,并在此处向您更新结果。感谢您的建议! @Timothy,既然你有一个新问题,请在 Stack Overflow 上再问一个问题。这样你会得到更好的回应,而不是在 cmets 中问更多问题。请务必发布与 DataGridView 数据填充和 aspx 相关的代码。以上是关于C# 将 DataTable 绑定到现有 DataGridView 列定义的主要内容,如果未能解决你的问题,请参考以下文章
无法刷新绑定到 DataTable 的 DataGridView
将DataTable数据绑定到DataGrid - 代码背后