<Style TargetType="TextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Border BorderBrush="Red" CornerRadius="2" />
<ScrollViewer x:Name="PART_ContentHost" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<Label x:Name="watermarklabel" Height="40" Content="{TemplateBinding Tag}" Foreground="Gray"/>
</Grid>
<ControlTemplate.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Value="True">
<Condition.Binding>
<MultiBinding Converter="{StaticResource Multi}">
<!--<Binding Path="Text" ElementName="txt1"/>-->
<Binding RelativeSource="{RelativeSource Mode=TemplatedParent}" Path="Text"/>
</MultiBinding>
</Condition.Binding>
</Condition>
</MultiDataTrigger.Conditions>
<Setter Property="Visibility" TargetName="watermarklabel" Value="Collapsed"/>
</MultiDataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
这里我想在文本框文本为空且不为空的情况下启用/禁用标签(即水印)。在多重绑定(bind)中,我试图使用 TemplatedParent 访问文本属性。但是当文本更改时它没有命中转换器。
当我使用元素名称访问它时,一切都很好。
但是我想把这个变成通用的..
如何让它发挥作用?
提前致谢..
最佳答案
这实际上令人惊讶地很难做到正确。互联网上有十几种不同的几乎正确的答案,但很少或没有完全正确的答案。
我最接近于让它正常工作的方法是在运行时根据您正在评估的条件将一个文本 block 动态地注入(inject)到标准文本框的 ControlTemplate 中。
动态注入(inject)避免了必须重新实现整个控制模板,并且假设控制模板在版本之间不会转换太多,还避免了每次内置主题更改时都必须创建新的 ControlTemplates 的维护点.
注入(inject)元素而不是修改现有文本元素可避免用户以不希望的方式选择/操作水印文本的各种问题。
避免覆盖解决方案:z 顺序和裁剪问题不值得付出努力(我曾经尝试使用装饰器来做到这一点,而不是正确的调用)
不要忘记验证文本框上的拖/放和复制/粘贴操作是否按预期使用水印。
IIRC,我使用附加属性完成此操作,因此水印不需要新控件。相反,它在可视化树中搜索它可以找到的第一个可行的水印目标,并在那里应用水印。这让它也可以在组合框中工作,例如,无需额外的工作。
关于c# - 水印文本框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23797303/