WPF Error: Cannot find governing FrameworkElement for target element
A slightly shorter alternative to using a StaticResource
as in the accepted answer is x:Reference
:
<StackPanel>
<!--Set the DataContext here if you do not want to inherit the parent one-->
<FrameworkElement x:Name="ProxyElement" Visibility="Collapsed"/>
<DataGrid>
<DataGrid.Columns>
<DataGridTextColumn
Header="{Binding DataContext.Whatever, Source={x:Reference ProxyElement}}"
Binding="{Binding ...}" />
</DataGrid.Columns>
</DataGrid>
</StackPanel>
The main advantage of this is: if you already have an element which is not a DataGrid's ancestor (i.e. not the StackPanel
in the example above), you can just give it a name and use it as the x:Reference
instead, hence not needing to define any dummy FrameworkElement
at all.
If you try referencing an ancestor, you will get a XamlParseException
at run-time due to a cyclical dependency.
Sadly any DataGridColumn
hosted under DataGrid.Columns
is not part of Visual
tree and therefore not connected to the data context of the datagrid. So bindings do not work with their properties such as Visibility
or Header
etc (although these properties are valid dependency properties!).
Now you may wonder how is that possible? Isn't their Binding
property supposed to be bound to the data context? Well it simply is a hack. The binding does not really work. It is actually the datagrid cells that copy / clone this binding object and use it for displaying their own contents!
So now back to solving your issue, I assume that HeaderItems
is a property of the object that is set as the DataContext
of your parent View. We can connect the DataContext
of the view to any DataGridColumn
via something we call a ProxyElement
.
The example below illustrates how to connect a logical child such as ContextMenu
or DataGridColumn
to the parent View's DataContext
<Window x:Class="WpfApplicationMultiThreading.Window5"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vb="http://schemas.microsoft.com/wpf/2008/toolkit"
Title="Window5" Height="300" Width="300" >
<Grid x:Name="MyGrid">
<Grid.Resources>
<FrameworkElement x:Key="ProxyElement" DataContext="{Binding}"/>
</Grid.Resources>
<Grid.DataContext>
<TextBlock Text="Text Column Header" Tag="Tag Columne Header"/>
</Grid.DataContext>
<ContentControl Visibility="Collapsed"
Content="{StaticResource ProxyElement}"/>
<vb:DataGrid AutoGenerateColumns="False" x:Name="MyDataGrid">
<vb:DataGrid.ItemsSource>
<x:Array Type="{x:Type TextBlock}">
<TextBlock Text="1" Tag="1.1"/>
<TextBlock Text="2" Tag="1.2"/>
<TextBlock Text="3" Tag="2.1"/>
<TextBlock Text="4" Tag="2.2"/>
</x:Array>
</vb:DataGrid.ItemsSource>
<vb:DataGrid.Columns>
<vb:DataGridTextColumn
Header="{Binding DataContext.Text,
Source={StaticResource ProxyElement}}"
Binding="{Binding Text}"/>
<vb:DataGridTextColumn
Header="{Binding DataContext.Tag,
Source={StaticResource ProxyElement}}"
Binding="{Binding Tag}"/>
</vb:DataGrid.Columns>
</vb:DataGrid>
</Grid>
</Window>
The view above encountered the same binding error that you have found if I did not have implemented the ProxyElement hack. The ProxyElement is any FrameworkElement that steals the DataContext
from the main View and offers it to the logical child such as ContextMenu
or DataGridColumn
. For that it must be hosted as a Content
into an invisible ContentControl
which is under the same View.
I hope this guides you in correct direction.