DataGridView бросает исключение в диалоге ошибок по умолчанию из-за DataGridViewImageColumn

Я излагаю это, потому что слишком много времени, чтобы найти ответ в Интернете, и это, вероятно, общая проблема - это второй раз, когда я испытал это в своем приложении.

Когда новая строка с DataGridViewImageCell становится видимой и не имеет значения по умолчанию, мой DataGridView выдает следующее исключение:

В DataGridView произошло следующее исключение:

System.ArgumentException: параметр недействителен. в  System.Drawing.Image.FromStream(поток потока, логический  useEmbeddedColorManagement, Boolean validateImageData) "

В моей настройке я создаю DataGridViewImageColumns в Visual Studio Designer, а затем привязываю эти столбцы к DataColumns в DataTable, устанавливая свойства DataPropertyName в DataGridViewImageColumns в соответствии с DataColumns типа: byte [].

Тем не менее, он по-прежнему выбрасывает это исключение, когда DataGridViewImageColumn в новой строке становится видимым.

Есть два обходных решения, которые работали для меня:

  • Снимите флажок "Включить добавление" в конструкторе - затем добавьте строки программно - с помощью кнопок и т.д. - Я думаю, что это то, что я сделал в первый раз.
  • Обработайте событие DataError DataGridView следующим образом:

        private void dataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {
            if (dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value == DBNull.Value)
            {
                e.Cancel = true;
            }
        }
    

Это вариант, с которым я сейчас пользуюсь, но я не поклонник подавления исключений, и я вижу задержку в создании строки DataGridView из-за броска + Catch обработчиком.

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

... который не работает.

Другой параметр включал установку столбца CellTemplate в тип, полученный из DataGridViewImageColumn со значением по умолчанию null или DBNull.Value.

Это немного поздно для этого сейчас - я был на этом весь день.

Я, вероятно, собираюсь пойти на свой вариант 2, но может ли кто-нибудь сказать мне, как получить вариант 3/4 для работы? Есть ли лучший подход для этого?

Ответ 1

Мое решение: удалите столбец сразу после его добавления (подробная причина в конце). Следующий код удаляет все потенциальные столбцы изображения, вы можете настроить его, если ваша схема не является динамической, и вы знаете, что вы хотите оставить:

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; вызывает изменение бизнес-объекта! Это причина, по которой я советую просто удалить столбец.

Ответ 2

Эти проблемы вызваны некоторыми типами изображений и 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); 
            }

Ответ 3

Я получал эту проблему, потому что некоторые из моих изображений мы JPEGS и некоторые были PNG.

Все PNG вызывали ошибку.

Я удалил все PNG, и я не получаю ошибок при прокрутке вниз по сетке.