Introduction

The columns of DataGrid.Columns do not inherit the DataContext of the DataGrid element, so you cannot easily bind DataGrid Headers of Columns with the default binding expression. This is caused by not inheriting from FrameworkElement. The following solution presented to overcome this problem.



Description

There are several solutions for this problem. Let's introduce the simplest solution (in my opinion). Since DataGridColumn does not inherit the DataContext of the superior element, you have to indicate the DataContext to use. This can be easily done as the following code snippet shows.

<DataGrid>
  <DataGrid.Columns>
    <DataGridTemplateColumn>
      <DataGridTemplateColumn.Header>
        <TextBlock Text="{Binding DataContext.HeaderNameText, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
      </DataGridTemplateColumn.Header>
    </DataGridTemplateColumn>
  </DataGrid.Columns>
<DataGrid>

As you can see the header is defined by using a TextBlock. The Text property of the TextBlock is bound to the property HeaderNameText of the DataContext of the DataGrid. In a similar way, you could use your own DataContext for the DataGridColumns. By defining the header in this way you could further customize your header by using further elements, e.g. Images. The DataContext of the DataGrid is set in code.

Data data = new Data();
data.HeaderNameText = "Header2";
data.Items = new List<string>() { "Item1", "Item2" };
  
DataContext = data;

The DataContext is an own object containing the values of the DataGrid and the Header name.

public class Data
{
  public string HeaderNameText
  {
    get;
    set;
  }
  
  public List<string> Items
  {
    get;
    set;
  }
}



References