web-dev-qa-db-ja.com

C#DataTableを既存のDataGridView列定義にバインドする

私はNullReferenceExceptionに苦しんでおり、ここの誰かが私を正しい方向に向けることができることを願っています。 DataTableを作成してデータを入力し、その結果をDataGridViewコントロールに表示しようとしています。基本的なコードが続き、新しいUpdateResults_Delegateを呼び出した時点で実行がNullReferenceExceptionで停止します。奇妙なことに、QueryEventEntriesから返す前にentries.Rows.Countを正常にトレースできるので、少なくとも1)エントリがnull参照ではなく、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に割り当てようとしています。

エントリDataTableの行を繰り返し処理して、テーブルに期待されるデータが含まれていることを確認してから、DataGridViewのデータソースとして割り当てました。

foreach (DataRow row in entries.Rows)
{
    System.Diagnostics.Trace.WriteLine(
        String.Format("{0} {1} {2}", row[0], row[1], row[2]));
}

DataGridViewの列の1つは、event_type値をスタイル化するためのカスタムDataGridViewColumnです。元の投稿でこれについて言及していなかったことをお詫びしますが、それが私の問題にとって重要であることに気づいていませんでした。この列を一時的に標準のDataGridViewTextBoxColumnコントロールに変換しましたが、例外は発生していません。

DataTableのフィールドは、DataGridViewのデザインビューで事前に指定されているフィールドのリストに追加されます。レコードの値は、これらの追加されたフィールドに入力されています。ランタイムがセルをレンダリングしようとすると、null値が提供されます(がレンダリングされる値が実行されるため、2列以上になります)。

これに照らして、私は質問のタイトルを付け直し、タグを付け直しています。これを経験した他の人が、DataTableをDataGridViewの既存の列定義にバインドする方法を教えてくれれば幸いです。

13
Timothy

各列のDataPropertyNameプロパティがDataColumnColumnNameの対応する名前に設定されていることを確認する必要があります。

DataGridViewAutoGenerateColumnsプロパティをfalseに設定する必要がある場合もあります。

私は解決策を見つけました ここ

27
Timothy

UpdateResults内でエラーが発生した場合は、dataGridViewがnullのように聞こえます。

private void UpdateResults(DataTable entries)
{
    dataGridView.DataSource = entries; // when is dataGridView set?
}
0
Samuel Neff