为什么我的自定义WPF文本框控件不显示此水印?
我在一个名为CustomControls
的新WPF项目中完成了以下操作。为什么我的自定义WPF文本框控件不显示此水印?
步骤1:创建了Controls
文件夹。添加了一个名为WatermarkTextBox.cs
的新文件。加入此C#代码文件中:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace Controls
{
public class WatermarkTextBox : TextBox
{
public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register("Watermark", typeof(String), typeof(WatermarkTextBox), new PropertyMetadata(String.Empty));
public String Watermark
{
get { return (String)GetValue(WatermarkProperty); }
set { SetValue(WatermarkProperty, value); }
}
}
}
步骤2:内Controls
文件夹,添加标题WatermarkTextBox.xaml
一个新的文件。新增此XAML文件中:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:controls="clr-namespace:Controls">
<Style TargetType="{x:Type controls:WatermarkTextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Style.Resources>
<VisualBrush x:Key="WatermarkBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="{Binding Watermark}" FontFamily="Segoe UI" FontSize="20" Foreground="LightGray" Padding="5" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource WatermarkBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource WatermarkBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
步骤3:创建Themes
文件夹。添加一个新的文件标题为Generic.xaml
它。在文件中添加此XAML:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/CustomControls;component/Controls/WatermarkTextBox.xaml" />
</ResourceDictionary.MergedDictionaries>
步骤4:在MainWindow.xaml
:新增xmlns:controls="clr-namespace:Controls"
,并定义了一个新WatermarkTextBox
:
<controls:WatermarkTextBox x:Name="Hostname" Height="40" FontFamily="Segoe UI" FontSize="20" VerticalContentAlignment="Center" Watermark="Hello, world."/>
我看到的文本框,这个自定义控制是基于,但我没有看到我为它扩展的水印。为什么会这样,以及如何渲染我的水印?附:我应该注意,如果我将XAML中的{Binding Watermark}
更改为硬编码字符串,水印会显示出来。此外,如果我调试我的代码,我看到WatermarkTextBox
选取正确的值...那么为什么XAML不显示它?有人甚至可以调试这些东西?
诀窍是使用名为混合为Visual Studio Windows应用程序编辑现有的WatermarkTextBox
的默认模板和扩展它引入Grid
其中不仅包括内容滚动视图也是一个新的标签的房子水印。总之,我不得不做出这个改变WatermarkTextBox.xaml
:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:controls="clr-namespace:Controls">
<Style TargetType="{x:Type controls:WatermarkTextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:WatermarkTextBox">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<Grid>
<ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
<Label Cursor="IBeam" Visibility="Hidden" x:Name="WatermarkText" Content="{TemplateBinding Watermark}" FontFamily="Segoe UI" FontSize="20" Foreground="LightGray" Padding="5" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="BorderBrush" TargetName="border" Value="#FF569DE5"/>
</Trigger>
<Trigger Property="Text" Value="{x:Static system:String.Empty}">
<Setter Property="Visibility" Value="Visible" TargetName="WatermarkText" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Visibility" Value="Visible" TargetName="WatermarkText" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
编辑:如果你想在生产这样做,再想想。我心想,“哦,如果要扩展每一个我需要的功能来提供这样的功能,那就太好了。”不幸的是一些控制类,如PasswordBox
是密封,使这在这些情况下的一个有争议的一点。 事实上,由于大多数黑客或扩展都这样做,因此以编程方式在与您的TextBox
相同的位置显示和隐藏标签会更容易。
检查我的答案在这里http://stackoverflow.com/questions/37995806/textpreview-for-textbox/37997102#37997102 –