我之所以提出这个问题,是因为在网上找到答案花了太长时间,这可能是一个常见问题 - 这是我第二次在我的应用程序上遇到它。
当带有 DataGridViewImageCell 的新行变得可见,并且没有设置默认值时,我的 DataGridView 会抛出以下异常:
DataGridView 中发生以下异常:
System.ArgumentException:参数无效。在 System.Drawing.Image.FromStream(Stream 流, 布尔值 使用EmbeddedColorManagement,布尔值validateImageData)”
在我的设置中,我在 Visual Studio Designer 中创建 DataGridViewImageColumns,然后通过设置 DataGridViewImageColumns 的 DataPropertyName 属性以匹配类型为 byte[] 的 DataColumns,将这些列绑定到 DataTable 中的 DataColumns。
但是,当新 Row 中的 DataGridViewImageColumn 变得可见时,它仍然会抛出此异常。
有两种对我有用的解决方法:
像这样处理DataGridView的DataError事件:
private void dataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
if (dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value == DBNull.Value)
{
e.Cancel = true;
}
}
这是我现在要使用的选项,但我不喜欢抑制异常,并且我可以看到由于处理程序的 throw + Catch 导致创建 DataGridView 行的延迟。
MSDN(http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewimagecolumn.aspx)表示您可以处理 RowsAdded 事件并强制为空值。我试过这个:
private void dataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
foreach (DataGridViewCell cell in dataGridView1.Rows[e.RowIndex].Cells)
{
if (cell.GetType() == typeof(DataGridViewImageCell))
{
cell.Value = DBNull.Value;
}
}
}
...这不起作用。
另一个选项涉及将 Column CellTemplate 设置为从 DataGridViewImageColumn 派生的类型,默认值为 null 或 DBNull.Value。
现在有点晚了——我已经在这件事上待了一整天了。
我可能会选择选项 2,但是谁能告诉我如何让选项 3/4 发挥作用?有没有最好的方法?
我的解决方案:添加后立即删除该列(详细原因在最后)。以下代码删除所有潜在的图像列,如果您的架构不是动态的并且您知道要遗漏什么,您可能需要自定义此列:
public Form1()
{
InitializeComponent();
dataGridView1.ColumnAdded += dataGrid_ColumnAdded;
}
void dataGrid_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
{
if (e.Column.CellType == typeof(DataGridViewImageCell))
dataGridView1.Columns.Remove(e.Column);
}
所以当涉及到实际绑定时
DataTable table = dataTableCombo.SelectedItem as DataTable;
dataGridView1.DataSource = table;
填充单元格将在添加(和删除更正)列后发生。并且异常不会以这种方式发生。
此外,在您的
dataGridView1_RowsAdded
事件处理程序中请注意:不仅有 e.RowIndex
,还有 e.RowCount
,而且可能是 e.RowCount > 1
!所以我首先尝试:
void dataGrid_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
for (int i = e.RowIndex; i < e.RowIndex + e.RowCount; i++)
{
foreach (DataGridViewCell cell in dataGridView1.Rows[i].Cells)
{
if (cell.GetType() == typeof(DataGridViewImageCell))
{
cell.Value = DBNull.Value;
}
}
}
}
但我还是有一些例外。另外,如果您的绑定是双向的,请小心,因为
cell.Value = DBNull.Value;
会导致业务对象发生更改!这就是我建议删除该列的原因。
这个问题是由某些 image 和 varbinary 列类型引起的,我的解决方案是创建其他数据数据表并将所有列和单元格值设置为字符串类型:
var clonedDT = dt.Clone();
for (int i = 0; i < clonedDT.Columns.Count; i++)
{
clonedDT.Columns[i].DataType = typeof(String);
}
for (int j = 0; j < dt.Rows.Count;j++ )
{
var newRow = clonedDT.NewRow();
for (int i = 0; i < dt.Columns.Count; i++)
{
newRow.SetField(i, Convert.ToString(item.Value.Rows[j] [i]));
}
clonedDT.Rows.Add(newRow);
}
我遇到这个问题是因为我的一些图像是 JPEG,有些是 PNG。
所有 PNG 都会导致抛出错误。
我删除了所有 PNG,当我向下滚动网格时没有出现任何错误。
它不起作用的原因是因为线路 if (dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value == DBNull.Value)
不能将值与空值进行比较
您需要通过将行更改为来切换它
if (DBNull.Value == dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value)
这会起作用。