为什么这个数据绑定不起作用? (WPF)
我的数据绑定不起作用,我不明白为什么。我在输出窗口中收到的消息是:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是我的用户控件是从 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.