<UserControl x:Class="WatermarkTextBox"
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"
mc:Ignorable="d"
d:DesignHeight="30"
d:DesignWidth="250">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</UserControl.Resources>
<Border>
<Grid x:Name="grid">
<TextBlock Text="{Binding Watermark, FallbackValue=This prompt dissappears as you type...}"
Visibility="{Binding ElementName=txtUserEntry, Path=Text.IsEmpty, Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBox Name="txtUserEntry"
Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</Border>
</UserControl>
上面的代码显示了我的
WatermarkTextBox
控件。在文件后面的代码中,我设置了 DataContext
。我省略了控件 DP 的所有代码。
public WatermarkTextBox()
{
InitializeComponent();
grid.DataContext = this;
}
我必须将
DataContext
绑定到网格,否则水印和实际文本的 Text
属性将不会显示。现在的问题是我无法将Background
的Border
设置在Grid
之外。
我尝试了下面的代码,但只设置了
Background
的 Border
,而不是水印和实际文本。
public WatermarkTextBox()
{
InitializeComponent();
this.DataContext = this;
grid.DataContext = this;
}
在这样的 UserControl 中,您永远不应该将 DataContext 显式设置为
this
或其他任何值,因为当您在应用程序中的某个位置使用 UserControl 时,DataContext 通常是在外部设置的。外部应用的 DataContext 通常是应用程序视图模型(的一部分)。
您应该更改内部绑定,以便它们使用显式
RelativeSource
:
<TextBlock
Text="{Binding Path=Watermark,
RelativeSource={RelativeSource AncestorType=UserControl},
FallbackValue=This prompt dissappears as you type...}"
Visibility="{Binding ElementName=txtUserEntry,
Path=Text.IsEmpty,
Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBox
Name="txtUserEntry"
Text="{Binding Path=Text,
UpdateSourceTrigger=PropertyChanged,
RelativeSource={RelativeSource AncestorType=UserControl}}" />
然后从 UserControl 的构造函数中删除任何 DataContext 赋值。
参见例如这个答案(以及许多其他类似的答案)详细讨论了这个主题。
@Clemens 答案的附录:
为了避免为每个控件设置
RelativeSource={RelativeSource AncestorType=UserControl}
,请在用户控件中提供一个根元素来获取 DataContext。
<UserControl x:Class="UserControlBindingIssue.TestUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:UserControlBindingIssue"
d:DataContext="{d:DesignInstance Type=local:TestUserControl,
IsDesignTimeCreatable=True}"
mc:Ignorable="d">
<ContentControl DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:TestUserControl}}}">
<TextBox Width="100"
Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}" />
<!-- Other controls -->
</ContentControl>
</UserControl>