I have stripped down my problem to a minimal example: My DataGrid is defined by a ControlTemplate and in that ControlTemplate I cannot bind to anything from my ViewModel.
This is the simplified ViewModel:
public class ViewModel : PropertyChangedBase
{
private string text1;
public ViewModel()
{
this.text1 = "tx1!";
}
public string Text1
{
get { return text1; }
set
{
if (value == text1) return;
text1 = value;
NotifyOfPropertyChange(() => Text1);
}
}
}
I tried to bind to Text1
with several methods. Most things I find via Google suggest FindAncestor
but it did not work either:
<Window x:Class="DataGridTemplateBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DataGridTemplateBinding"
Title="MainWindow" Height="350" Width="525"
x:Name="LayoutRoot"
>
<Window.Resources>
<ControlTemplate x:Key="TableTemplate">
<DataGrid>
<DataGrid.Columns>
<DataGridTextColumn Header="Column 1" />
<!-- by ElementName -->
<DataGridTextColumn Header="{Binding DataContext.Text1, ElementName=LayoutRoot}" />
<DataGridTextColumn Header="{Binding Text1, ElementName=LayoutRoot}" />
<!-- by Ancestor type (Window) -->
<DataGridTextColumn Header="{Binding DataContext.Text1, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" />
<DataGridTextColumn Header="{Binding Text1, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" />
<!-- by templated parent -->
<DataGridTextColumn Header="{Binding DataContext.Text1, RelativeSource={RelativeSource TemplatedParent}}" />
<DataGridTextColumn Header="{Binding Text1, RelativeSource={RelativeSource TemplatedParent}}" />
<!-- by self?? -->
<DataGridTextColumn Header="{Binding DataContext.Text1, RelativeSource={RelativeSource Self}}" />
<DataGridTextColumn Header="{Binding Text1, RelativeSource={RelativeSource Self}}" />
<DataGridTextColumn Header="{Binding Content.DataContext.Text1, RelativeSource={RelativeSource TemplatedParent}}" />
<DataGridTextColumn Header="{Binding Content.Text1, RelativeSource={RelativeSource TemplatedParent}}" />
<DataGridTextColumn Header="{Binding DataContext.Text1}" />
<DataGridTextColumn Header="{Binding Text1}" />
<DataGridTextColumn Header="Column End" />
</DataGrid.Columns>
</DataGrid>
</ControlTemplate>
</Window.Resources>
<Window.DataContext>
<local:ViewModel />
</Window.DataContext>
<Grid>
<DataGrid Template="{StaticResource TableTemplate}" />
</Grid>
</Window>
How can a column in the template bind to anything in the ViewModel? I cannot image this would not be possible.
For completeness, these are the errors logged to output. Their order does not correspond with the order of the XAML.
System.Windows.Data Error: 40 : BindingExpression path error: 'DataContext' property not found on 'object' ''DataGridTextColumn' (HashCode=28365320)'. BindingExpression:Path=DataContext.Text1; DataItem='DataGridTextColumn' (HashCode=28365320); target element is 'DataGridTextColumn' (HashCode=28365320); target property is 'Header' (type 'Object')
System.Windows.Data Error: 40 : BindingExpression path error: 'Text1' property not found on 'object' ''DataGridTextColumn' (HashCode=54811268)'. BindingExpression:Path=Text1; DataItem='DataGridTextColumn' (HashCode=54811268); target element is 'DataGridTextColumn' (HashCode=54811268); target property is 'Header' (type 'Object')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=DataContext.Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=55195297); target property is 'Header' (type 'Object')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=38845522); target property is 'Header' (type 'Object')
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1''. BindingExpression:Path=DataContext.Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=2399386); target property is 'Header' (type 'Object')
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1''. BindingExpression:Path=Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=31265986); target property is 'Header' (type 'Object')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=DataContext.Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=6837024); target property is 'Header' (type 'Object')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=17422861); target property is 'Header' (type 'Object')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Content.DataContext.Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=32669489); target property is 'Header' (type 'Object')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Content.Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=22361045); target property is 'Header' (type 'Object')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=DataContext.Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=7953856); target property is 'Header' (type 'Object')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=Text1; DataItem=null; target element is 'DataGridTextColumn' (HashCode=65911433); target property is 'Header' (type 'Object')
{Binding Text1}
should do it. Are you setting theDataContext
from anywhere else? – Mike EasonDataGrid
has in it's template anotherDataGrid
? – Novitchi S{Binding Text1}
does not do the trick. DataContext is only set for the Window. App.xaml & co. are standard, this is nearly all the code in the minimal example project. – ZoolWayDataGrid
is coming from a ResourceDictionary in the full-blown application. But even this minimalistic XAML does not work. – ZoolWay