1

Possible Duplicate:
Wpf Toolkit. Bind DataGrid Column Header to DynamicResource
WPF Error: Cannot find govering FrameworkElement for target element

I am creating a WPF application using the MVVM pattern, so on my view I am trying to bind the column header of a DataGrid column to a property on my view model which is the data context of the view that the DataGrid is in.

XAML:

<DataGrid Name="DailyData" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False" ItemsSource="{Binding Path=DailyDataViewModels}" HorizontalAlignment="Stretch">
                    <DataGrid.Columns>
                        <DataGridTextColumn Header="{Binding InflowVolumeLabel}" Binding="{Binding InflowVolume}"></DataGridTextColumn>
                    </DataGrid.Columns>
                </DataGrid>

However the header just shows up blank and does not seem to be trying to bind to the specified property, how can you bind a DataGrid column header?

Community
  • 1
  • 1
Alex Hope O'Connor
  • 9,354
  • 22
  • 69
  • 112
  • 1
    @parapurarajkumar: The `BindingMarkupExtension` considers any unkeyed value to be the `Path`, so yes it is intentional, but it also is correct. – user7116 Nov 10 '11 at 03:56

1 Answers1

1

You've run into a neat problem with the DataGrid.Columns collection, namely they are not a member of the same visual tree and thus only the Binding property appears to work.

The only approach I've found that works is to add an attached property to the DataGrid which will apply the headers after the data is loaded.

public static readonly DependencyProperty ColumnHeadersProperty =
    DependencyProperty.RegisterAttached(
        "ColumnHeaders",
        typeof(IDictionary<string, string>),
        typeof(DataGrid),
        new UIPropertyMetadata(
            new Dictionary<string,string>(),
            ColumnHeadersPropertyChanged));

public static IDictionary<string,string> GetColumnHeaders(DependencyObject obj)
{
    return (IDictionary<string, string>)obj.GetValue(ColumnHeadersProperty);
}

public static void SetColumnHeaders(DependencyObject obj,
    IDictionary<string, string> value)
{
    obj.SetValue(ColumnHeadersProperty, value);
}

static void ColumnHeadersPropertyChanged(DependencyObject sender,
    DependencyPropertyChangedEventArgs e)
{
    var dataGrid = sender as DataGrid;
    if (dataGrid != null && e.NewValue != null)
    {
        dataGrid.AutoGeneratingColumn += AddColumnHeaders;
    }
}

static void AddColumnHeaders(object sender,
    DataGridAutoGeneratingColumnEventArgs e)
{
    var headers = GetColumnHeaders(sender as DataGrid);
    if (headers.ContainsKey(e.PropertyName))
    {
        e.Column.Header = headers[e.PropertyName];
    }
}

Potentially used like (could be improved):

// you could change it to use Column.DisplayIndex
this.dataGrid.SetValue(
    DataGridEx.ColumnHeadersProperty,
    new Dictionary<string, string>
    {
        { "PropertyName1", "Header 1" },
        { "PropertyName2", "Header 2" },
        { "PropertyName3", "Header 3" },
    });
user7116
  • 63,008
  • 17
  • 141
  • 172