我一直在尝试构建一个带有提示的文本框,当它显示为空时显示。 我在一个样式中设置提示文本时遇到问题。
准确地说,这个有效(也就是说,它正确绑定):
<TextBox Tag="hint text">
<TextBox.Background>
<VisualBrush Stretch="None">
<VisualBrush.Visual>
<TextBlock Text="{Binding Tag, RelativeSource={RelativeSource AncestorType=TextBox}}" FontStyle="Italic" Foreground="LightGray" />
</VisualBrush.Visual>
</VisualBrush>
</TextBox.Background>
</TextBox>
但是,当我将它移动到Style时,它不会:
<Style TargetType="TextBox" x:Key="stlHintbox">
<Style.Triggers>
<DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource Mode=Self}}" Value="">
<Setter Property="Background">
<Setter.Value>
<VisualBrush Stretch="None">
<VisualBrush.Visual>
<TextBlock Tag="inner" Text="{Binding Tag, RelativeSource={RelativeSource AncestorType=TextBox}}"
FontStyle="Italic" Foreground="LightGray" />
</VisualBrush.Visual>
</VisualBrush>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<TextBox Tag="hint text" Style="{StaticResource stlHintbox}" />
那捕获的是什么?如何从样式中绑定到祖先属性?
答案 0 :(得分:14)
问题不在于RelativeSource,而在于您使用VisualBrush的方式。回想一下,样式在您应用它们的元素之间共享。您的示例不起作用的原因是,实际上您尝试与多个父文本框共享单个文本框(标记为“内部”的文本框)。
要了解这是一个问题,请尝试一个思想实验:内部文本框创建一次(粗略地说,这将在创建样式时发生)。当您使用RelativeSource绑定时,应该选择应用样式的哪个文本框作为内部文本框的祖先?
这就是WPF中存在DataTemplates和ControlTemplates的原因。他们不是直接实际显示视觉效果,而是定义一个模板,允许根据需要创建多个视觉副本。
答案 1 :(得分:5)
Reativesource无法按预期工作。 最好使用控件模板创建水印文本框。但你的版本可以工作:
<Window.Resources>
<Style TargetType="TextBox" x:Key="stlHintbox">
<Style.Triggers>
<DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource Mode=Self}}" Value="">
<Setter Property="TextBox.Background">
<Setter.Value>
<VisualBrush Stretch="None" Visual="{Binding ElementName=hintText}"/>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<TextBox Tag="hint text" x:Name="myTextBox" Style="{StaticResource stlHintbox}" />
<Border Visibility="Hidden">
<TextBlock x:Name="hintText" Text="{Binding Tag, ElementName=myTextBox}" FontStyle="Italic" Foreground="LightGray" />
</Border>
</StackPanel>