12

ウェブで答えを見つけるのに時間がかかりすぎたため、これを掲載しています。これはおそらく一般的な問題です。アプリでこれを経験したのは 2 回目です。

DataGridViewImageCell を含む新しい行が表示され、デフォルト値が設定されていない場合、DataGridView は次の例外をスローします。

DataGridView で次の例外が発生しました:

System.ArgumentException: パラメーターが無効です。System.Drawing.Image.FromStream (ストリーム ストリーム、ブール値の useEmbeddedColorManagement、ブール値の validateImageData) で"

私のセットアップでは、Visual Studio Designer で DataGridViewImageColumns を作成し、DataGridViewImageColumns の DataPropertyName プロパティを Type: byte[] の DataColumns と一致するように設定して、これらの列を DataTable の DataColumns にバインドします。

ただし、新しい行の DataGridViewImageColumn が表示されると、この例外がスローされます。

私のために働いた2つの回避策があります:

  1. デザイナーで「追加を有効にする」オプションのチェックを外し、ボタンなどを使用してプログラムで行を追加します。これが私が最初に行ったことだと思います。
  2. DataGridView の DataError イベントを次のように処理します。

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

それは私が今のところ行っているオプションですが、私は例外を抑制するのが好きではなく、ハンドラーによるスロー + キャッチによる DataGridView 行の作成の遅延を見ることができます。

MSDN ( http://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewimagecolumn.aspx ) は、RowsAdded イベントを処理して null 値を強制できると述べています。私はこれを試しました:

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

...うまくいきませんでした。

もう 1 つのオプションでは、Column CellTemplate を DataGridViewImageColumn から派生した Type に設定し、デフォルト値を null または DBNull.Value に設定しました。

今は少し遅いです-私は一日中これにいました。

おそらくオプション 2 を使用するつもりですが、オプション 3/4 を機能させる方法を誰か教えてもらえますか? これに最適なアプローチはありますか?

4

3 に答える 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.RowIndexe.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;は、ビジネス オブジェクトが変更されるため注意してください。それが、列を削除することをお勧めする理由です。

于 2013-10-28T20:59:56.103 に答える
0

この問題は、一部の画像および 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); 
            }
于 2015-02-16T18:59:11.747 に答える