Search code examples
wpfdatatabledatagrid

No rows or columns when binding a DataGrid to a DataTable


I am trying to show the contents of a SQL Server table in a DataGrid. I've reduced it to the most basic version and am leaving everything default, and am not seeing any column headings nor any rows.

Here is my code-behind:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        Test1DataSet test1DataSet = new Test1DataSet();
        Test1DataSetTableAdapters.AdminUserTableAdapter tableAdapter =
            new Test1DataSetTableAdapters.AdminUserTableAdapter();
        tableAdapter.Fill(test1DataSet.AdminUser);

       Test1DataSet.AdminUserDataTable dataTable = tableAdapter.GetData();
        Console.WriteLine(dataTable.Count);

        dataGrid.DataContext = dataTable.DefaultView;
    }
}

Here is the xaml:

<Grid Name="Grid1">
    <DataGrid Margin="25" Name="dataGrid">
      <!--  <DataGrid.Columns>
            <DataGridTextColumn Header="id" Binding="{Binding id}" />
            <DataGridTextColumn Header="Name" Binding="{Binding LastName}" />
        </DataGrid.Columns> -->
    </DataGrid>
</Grid>

Table definition: CREATE TABLE [dbo].[AdminUser] ( [id] INT IDENTITY (1, 1) NOT NULL, [EmployeeNumber] NVARCHAR (30) NOT NULL, [FirstName] NVARCHAR (100) NULL, [LastName] NVARCHAR (100) NULL, [isSA] BIT NOT NULL, [isDA] BIT NOT NULL );


Solution

  • The FramworkElement.DataContext property is meant to serve as context for data binding. It allows to define source agnostic bindings that can be reused when the data source changes.
    Data binding overview (WPF .NET)

    When you want to show data in a ItemsControl you must always assign a data source to the ItemsControl.ItemsSource property (and not to the FrameworkElement.DataContext).

    Assign the data source using data binding (and DataContext):

    class MainWindow : Window
    {
      public DataTable TableData { get; }
    
      public MainWindow()
      {
        // Set DataContext for data binding,
        // where this MainWindow instance will implicitly serve as the data source.
        this.DataContext = this
      }
    }
    
    <Window>
      
      <!-- DataGrid inherits the DataContext of its parent (MainWindow) implicitly -->
      <DataGrid ItemsSource="{Binding TableData}" />
    </Window>
    

    Or if you don't use data binding:

    myDataGrid.ItemsSource = this.TableData.DefaultView;