0

I have this databinding that doesn't work and I can not figure ut why. The message that I am getting in output window is:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='MyProject.Controls.DetailDataControl', AncestorLevel='1''. BindingExpression:Path=IsEditing; DataItem=null; target element is 'TextBox' (Name='forenameTextBox'); target property is 'IsEnabled' (type 'Boolean')

The xaml is:

<ad:DocumentContent  x:Class="MyProject.Controls.DetailDataControl"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"         
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:ec="clr-namespace:MyProject.Controls"
      xmlns:ecc="clr-namespace:MyProject.Classes.Converters"
      xmlns:ad="clr-namespace:AvalonDock;assembly=AvalonDock"
      mc:Ignorable="d"
      d:DesignHeight="300" d:DesignWidth="300">
      <Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
           <Grid.RowDefinitions>        
               <RowDefinition Height="20"/>   
               <RowDefinition Height="Auto"/>
               <RowDefinition  Height="*"/>
               </Grid.RowDefinitions>
               <WrapPanel HorizontalAlignment="Right"  VerticalAlignment="Stretch" Grid.Row="0" >
                   <Button Content="Edit" HorizontalAlignment="Right"  Name="editButton1" VerticalAlignment="Stretch" Click="editButton1_Click" />
               </WrapPanel>
               <Grid x:Name="pDataGrid" Margin="10,10,10,10" Grid.Row="1">
               <Grid.Resources>
                    <ecc:InvertBooleanConverter  x:Key="boolConvert"/> 
               <Style x:Key="BaseStyle" TargetType="Control">
                   <Setter Property="HorizontalAlignment" Value="Stretch"/>
                   <Setter Property="VerticalAlignment" Value="Stretch"/>
                   <Setter Property="FontFamily" Value="Arial"/>
                   <Setter Property="FontSize" Value="12" />
               </Style>
               <Style TargetType="Label" BasedOn="{StaticResource BaseStyle}" > 
                   <Setter Property="HorizontalAlignment" Value="Stretch"/>
                   <Setter Property="VerticalAlignment" Value="Stretch"/>
                   <Setter Property="Foreground" Value="Blue"/>
               </Style>
               <Style TargetType="TextBox" BasedOn="{StaticResource BaseStyle}">
               </Style>
               <Style TargetType="DatePicker" BasedOn="{StaticResource BaseStyle}" > 
                   <Setter Property="HorizontalAlignment" Value="Stretch"/>
                   <Setter Property="VerticalAlignment" Value="Stretch"/>
                   <Setter Property="IsHitTestVisible"  Value="{Binding Path=IsEditing, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ec:DetailDataControl}}}" />
               </Style>
               <Style TargetType="ComboBox" BasedOn="{StaticResource BaseStyle}">
                   <Setter Property="IsEnabled" Value="{Binding Path=IsEditing, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ec:DetailDataControl}}}" />
               </Style>
               <Style TargetType="Button" BasedOn="{StaticResource BaseStyle}">
                   <Setter Property="Width" Value="75" />
               </Style>
               <Style TargetType="RowDefinition"   >
                   <Setter Property="Height" Value="30" /> 
                   <Setter Property="SharedSizeGroup" Value="RowzSize"/>
               </Style>
               <Style x:Key="LabelColumnStyle" TargetType="ColumnDefinition"  >
                   <Setter Property="Width" Value="*" /> 
                   <Setter Property="SharedSizeGroup" Value="LabelColumnszSize"/> 
               </Style> 
               <Style x:Key="TextColumnStyle" TargetType="ColumnDefinition"   > 
                   <Setter Property="Width" Value="3*" />
               </Style>
           </Grid.Resources>
           <Grid.RowDefinitions>
               <RowDefinition />
               <RowDefinition /> 
               <RowDefinition />  
               <RowDefinition /> 
               <RowDefinition />  
               <RowDefinition />  
               <RowDefinition />
               <RowDefinition />
           </Grid.RowDefinitions>
           <Grid.ColumnDefinitions>
               <ColumnDefinition Style="{StaticResource LabelColumnStyle}"/>
               <ColumnDefinition Style="{StaticResource TextColumnStyle}"/>
           </Grid.ColumnDefinitions> 
           <Label Content="forename" Grid.Column="0" Grid.Row="0" />
           <TextBox Grid.Column="1" Grid.Row="0" x:Name="forenameTextBox" Text="{Binding Path=Title}"  IsEnabled="{Binding Path=IsEditing, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ec:DetailDataControl}}}"/>
       </Grid>
       <TabControl Grid.Row="2" HorizontalAlignment="Stretch"  Name="tabControl1" VerticalAlignment="Stretch" >
           <TabItem Header="Address" Name="addresTabItem"> 
               <DataGrid  Name="addressDataGrid"  AutoGenerateColumns="False" ItemsSource="{Binding}" IsReadOnly="True"> 
                   <DataGrid.Columns>
                       <DataGridTextColumn Binding="{Binding Path='Order'}" Header="Order" Width="*" />
                       <DataGridTextColumn Binding="{Binding Path='Address1'}" Header="Address1"   Width="3*" /> 
                       <DataGridTextColumn Binding="{Binding Path='Address2'}" Header="Address2" Width="3*" />
                       <DataGridTextColumn Binding="{Binding Path='Postcode'}" Header="Postcode" Width="*" /> 
                       <DataGridTextColumn Binding="{Binding Path='TelNo'}" Header="TelNo" Width="*" />
                       <DataGridTextColumn Binding="{Binding Path='MovedToAddressDate', StringFormat={}\{0:dd/MM/yyyy\}}" Header="Moved Date" Width="*" />
                       <DataGridTemplateColumn>
                           <DataGridTemplateColumn.CellTemplate>  
                               <DataTemplate>
                                    <Button Content="Button" Tag="{Binding Path=ID}"  Name="editAddressButton" Click="editAddressButton_Click" />
                               </DataTemplate>
                           </DataGridTemplateColumn.CellTemplate>
                       </DataGridTemplateColumn>
                   </DataGrid.Columns>
               </DataGrid>
           </TabItem>
       </TabControl>
    </Grid> 
</ad:DocumentContent>

and C#'code is as follow:

public static readonly DependencyProperty IsEditingProperty = DependencyProperty.Register(
        "IsEditing", typeof(Boolean), typeof(DetailDataControl), new PropertyMetadata(false));
public Boolean IsEditing    
{
    get { return (Boolean)GetValue(IsEditingProperty); }
    set { SetValue(IsEditingProperty, value); }
}

Update1

A simplifed version:

Xaml code (user control)

<ad:DocumentContent x:Class="TestWpf.UserControl1"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:ad="clr-namespace:AvalonDock;assembly=AvalonDock"
          xmlns:ec="clr-namespace:TestWpf"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid x:Name="MainGrid" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
    <Grid.RowDefinitions>
        <RowDefinition Height="20"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition  Height="*"/>
    </Grid.RowDefinitions>
    <WrapPanel HorizontalAlignment="Right"  VerticalAlignment="Stretch" Grid.Row="0" >
        <Button Content="Edit" HorizontalAlignment="Right"  Name="editButton1" VerticalAlignment="Stretch" Click="button1_Click" />
    </WrapPanel>
    <Grid x:Name="pDataGrid" Margin="10,10,10,10" Grid.Row="1">
        <Grid.Resources>
            <Style TargetType="TextBox" >
                <Setter Property="IsEnabled" Value="{Binding Path=IsEditing, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ec:UserControl1}}}" />
            </Style>
        </Grid.Resources>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />

        </Grid.ColumnDefinitions>
        <TextBox x:Name="textBox1"  Grid.Column="0" Text="!234" />
        <TextBox x:Name="textBox2"    Grid.Column="1" />
    </Grid>
</Grid>
</ad:DocumentContent>

User control C# code:

namespace TestWpf
{
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : DocumentContent
{
    public static readonly DependencyProperty IsEditingProperty = DependencyProperty.Register(
          "IsEditing", typeof(Boolean), typeof(UserControl1), new PropertyMetadata(false));

    public Boolean IsEditing
    {
        get { return (Boolean)GetValue(IsEditingProperty); }
        set { SetValue(IsEditingProperty, value); }
    }
    public UserControl1()
    {
        InitializeComponent();
    }
    private void button1_Click(object sender, RoutedEventArgs e)
    {
        IsEditing = !IsEditing;
    }
}
}

I am not getting any binding error in output, but the binsing doesn't work.

Update2

Checking with Snoop, I found that UserControl1 is not the parent of textbox2 (!). I belive Avalon dock changing the parent type from UserControl1 to a different type. The parent of MainGrid is contentPresenter and there is no UserControl in the visual tree.

What can I do?

mans
  • 17,104
  • 45
  • 172
  • 321
  • Are you sure this is the relevant and up to date code that is causing that error? I'm not seeing anything about `forenameTextBox` in your XAML. – Merlyn Morgan-Graham Jul 17 '11 at 22:17
  • Sorry, updated with correct forename text box (I have several textbox that all are the same and the binding doesn't work on all of them so I only present one of them here for simplicity) – mans Jul 17 '11 at 22:31
  • Looks like your top level binding is to a collection for the datagrid, and a path of Title is bound to the text box. This seems to be in conflict. What is the top level object that you are binding to this control? – Dave Clemmer Jul 17 '11 at 22:36
  • @Dave, Thanks for your comment. I created a new project and delete all unnecessary code from the user control but it is not working. See update 1. – mans Jul 17 '11 at 22:47
  • Not able to repro with your simplified example (using a UserControl instead of a DocumentContent control). – Dave Clemmer Jul 17 '11 at 23:09
  • Thanks, I found the problem. It is AvalonDock that generate the problem. If I use usercontrol, it doesn't generate the error. Will post the code which works now. – mans Jul 17 '11 at 23:20
  • not sure if this one has been answered yet or not? But in any case, the issue for this one was caused (as per the error) by the binding source not being found. For future reference, an easy way to debug these is by creating a debugConverter which just triggers a breakpoint for that control. From there you can infer the DataContext and any parent references that the control has. Additional debugging would then involve changing the RelativeSource until you work out their intricacies. – fatty Jul 18 '11 at 03:49
  • You can use ElementName in the binding or you can use DataContext={Binding...} to explicitely bind your DataConext. –  Jul 18 '11 at 09:10

1 Answers1

0

The problem is that my usercontrol was created from DocumentContent (an AvalonDock object). If I create my control based on UserControl and then add it to a Document content it would work.

mans
  • 17,104
  • 45
  • 172
  • 321