我的WPF控件没有像我期望的那样呈现。具体来说,当我为用户控件的依赖项属性赋值时,如果其子控件发生错误,则该用户控件会尝试使用该值,并且子控件不会按原样呈现。
我把这个问题简化为一个简单的例子,如下所示。我创建了一个RedBox用户控件,它在红色边框内显示其内容,以及一个BlueBox用户控件,它应该在RedBox内的TextBlock中显示绑定文本。最后一部分失败了。我怀疑问题出在BlueBox.xaml的第35行,但这只是猜测。
RedBox.xaml
<UserControl
x:Class="WpfApplication1.RedBox"
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"
mc:Ignorable="d">
<ContentControl.Template>
<ControlTemplate TargetType="UserControl">
<Border BorderBrush="Red" BorderThickness="4" Padding="4">
<ContentPresenter Margin="3,0,0,0" Content="{TemplateBinding Content}" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</ContentControl.Template>
</UserControl>
RedBox.xaml.cs
namespace WpfApplication1
{
public partial class RedBox
{
public RedBox()
{
InitializeComponent();
}
}
}
BlueBox.xaml
<UserControl x:Class="WpfApplication1.BlueBox"
x:Name="UserControl"
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:wpfApplication1="clr-namespace:WpfApplication1"
mc:Ignorable="d">
<Border BorderBrush="Blue" BorderThickness="4" Padding="4">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Show the BlueBox's Text property value:" />
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding ElementName=UserControl, Path=Text}" />
<TextBlock Grid.Row="1" Grid.Column="0" Text="Show static text within a RedBox:" />
<wpfApplication1:RedBox Grid.Row="1" Grid.Column="1">
<TextBlock Text="Static Text" />
</wpfApplication1:RedBox>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Show the BlueBox's Text property value within a RedBox:" />
<wpfApplication1:RedBox Grid.Row="2" Grid.Column="1">
<TextBlock Text="{Binding ElementName=UserControl, Path=Text}" />
</wpfApplication1:RedBox>
</Grid>
</Border>
</UserControl>
BlueBox.xaml.cs
using System.Windows;
using System.Windows.Input;
namespace WpfApplication1
{
public partial class BlueBox
{
public BlueBox()
{
InitializeComponent();
}
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
name: "Text",
propertyType: typeof(string),
ownerType: typeof(BlueBox),
typeMetadata: new PropertyMetadata());
}
}
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wpfApplication1="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<wpfApplication1:BlueBox Text="Hi!" />
</Window>
如果我可以发布运行时MainWindow的屏幕截图,您会看到所有依赖项属性都正确连接,但是应该有一个带有“Hi!”的红框。在其中,根本就没有一个。 “输出”窗口给出了这个错误:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=UserControl'. BindingExpression:Path=Text; DataItem=null; target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
在研究错误“无法找到与引用绑定的源代码”时,我发现错误的一个常见原因是人们试图绑定到不在他们绑定的对象的可视树中的东西至。但我不认为这是我的问题,因为BlueBox在自己的TextBlock控件的可视树中,不是吗?
那是怎么回事?
更新
我发现如果我用以下代码替换BlueBox.xaml的第35行,它可以工作:
<TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type wpfApplication1:BlueBox}}, Path=Text}" />
这解决了我的问题。不过,我仍然感到困惑,为什么ElementName语法不起作用。我很感激任何见解。
答案 0 :(得分:4)
您的依赖项属性Text
的类型为String
。但您已将其默认值注册为new PropertyMetadata()
。
更改代码的这一部分:
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
name: "Text",
propertyType: typeof(string),
ownerType: typeof(BlueBox),
typeMetadata: new PropertyMetadata());
对此:
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
name: "Text",
propertyType: typeof(string),
ownerType: typeof(BlueBox));
这可能会解决您的问题。