Run this, and be confused:
<Window x:Class="Data_Grids.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<DataGrid
Name="r1"
ItemsSource="{Binding Path=.}">
</DataGrid>
<DataGrid
Name="r2"
ItemsSource="{Binding Path=.}">
</DataGrid>
</StackPanel>
</Window>
Codebehind:
using System.Data;
using System.Windows;
namespace Data_Grids
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataTable dt1, dt2;
dt1 = new DataTable();
dt2 = new DataTable();
dt1.Columns.Add("a-name", typeof(string));
dt1.Columns.Add("b-name", typeof(string));
dt1.Rows.Add(new object[] { 1, "Hi" });
dt1.Rows.Add(new object[] { 2, "Hi" });
dt1.Rows.Add(new object[] { 3, "Hi" });
dt1.Rows.Add(new object[] { 4, "Hi" });
dt1.Rows.Add(new object[] { 5, "Hi" });
dt1.Rows.Add(new object[] { 6, "Hi" });
dt1.Rows.Add(new object[] { 7, "Hi" });
dt2.Columns.Add("a.name", typeof(string));
dt2.Columns.Add("b.name", typeof(string));
dt2.Rows.Add(new object[] { 1, "Hi" });
dt2.Rows.Add(new object[] { 2, "Hi" });
dt2.Rows.Add(new object[] { 3, "Hi" });
dt2.Rows.Add(new object[] { 4, "Hi" });
dt2.Rows.Add(new object[] { 5, "Hi" });
dt2.Rows.Add(new object[] { 6, "Hi" });
dt2.Rows.Add(new object[] { 7, "Hi" });
r1.DataContext = dt1;
r2.DataContext = dt2;
}
}
}
I'll tell you what happens. The top datagrid is populated with column headers and data. The bottom datagrid has column headers but all the rows are blank.
The full stop character in the column names of the second table are incorrectly interpreted by the binding path parser. Look at the debug output while this example is running and you can see that the auto-generated columns have been bound to 'a' and 'b' rather than 'a.name' and 'b.name'
System.Windows.Data Error: 40 : BindingExpression path error: 'a' property not found on 'object' ''DataRowView' ... etc.
System.Windows.Data Error: 40 : BindingExpression path error: 'b' property not found on 'object' ''DataRowView' ... etc.
There are a number of different characters which have special meaning in a binding path including full stop ('.'), slash ('/'), square brackets ('[',']') and parenthesis ('(',')'), the parenthesis will cause your app to crash. These special characters can be escaped by surrounding the binding path with square brackets. More information about paths and character escaping can be found in the Binding Declarations Overview
To fix this you will have to set AutoGenerateColumns="False" and specify the column bindings in the xaml:
<DataGrid
x:Name="r2"
ItemsSource="{Binding .}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="a.name" Binding="{Binding Path=[a.name]}" />
<DataGridTextColumn Header="b.name" Binding="{Binding Path=[b.name]}" />
</DataGrid.Columns>
</DataGrid>
or programmatically in the code behind
r2.AutoGenerateColumns = false;
foreach( DataColumn column in dt2.Columns )
{
var gridColumn = new DataGridTextColumn()
{
Header = column.ColumnName,
Binding = new Binding( "[" + column.ColumnName + "]" )
};
r2.Columns.Add( gridColumn );
}
r2.DataContext = dt2;