为什么这个数据绑定不起作用? (WPF)

发布于 2024-11-24 07:36:33 字数 10424 浏览 0 评论 0原文

我的数据绑定不起作用,我不明白为什么。我在输出窗口中收到的消息是:

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')

Xaml 是:

<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>

并且 C# 代码如下:

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

简化版本:

Xaml 代码(用户控件)

<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>

用户控件 C# 代码:

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;
    }
}
}

我在输出中没有收到任何绑定错误,但是装箱不起作用。

Update2

通过 Snoop 检查,我发现 UserControl1 不是 textbox2 的父级(!)。我相信 Avalon 码头将父类型从 UserControl1 更改为其他类型。 MainGrid 的父级是 contentPresenter,并且可视化树中没有 UserControl。

我能做些什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

拥醉 2024-12-01 07:36:36

问题是我的用户控件是从 DocumentContent (一个 AvalonDock 对象)创建的。如果我基于 UserControl 创建控件,然后将其添加到文档内容中,它将起作用。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文