Search code examples
wpfdatagridado.netdatareader

Bind datagrid to datareader


I want to be able to enter SQL into a textbox and display the results in a WPF Datagrid. I thought to start with an SqlDataReader, and set the datagrid's ItemsSource to the data reader:

using (var cmd = conn.CreateCommand()) {
    cmd.CommandText = sql.Text;
    sqlResults.ItemsSource = cmd.ExecuteReader();
}

but this fails with the following error: Invalid attempt to call FieldCount when reader is closed, which I understand to mean that by the time WPF gets around to reading the FieldCount property of the row object, the using block has already been exited.

So I tried using LINQ and ToList, to get something that would persist in memory:

sqlResults.ItemsSource = cmd.ExecuteReader().Cast<DbDataRecord>().ToList();

but this only displays the 'FieldCount' for each row, which is apparently the only property which DbDataRecord has.

Some solutions I have considered:

  • Bind to a DataTable instead of a DataReader? But I don't need editing capabilities.
  • Select each row into an in-memory data structure? What data structure could I use? I can't use anonymous types, because the names and types of the columns change based on the SQL statement. If I use List<object>, how will the datagrid know to generate columns for each object in the list?
  • Create a custom type descriptor? It seems like overkill.

But I feel the solution should be very simple and easy. Am I missing something basic here?


Solution

  • Maybe a DataTable is overkill but it does what you need it to do.