样式化 WPF 密码框
Styling a WPF Passwordbox
我目前正在尝试执行以下操作:
如果未输入密码,则应显示文本 "Password"。
但是我的模板没有显示密码,如果我使用装饰器或滚动查看器,我无法更改文本的颜色。
你有什么想法来实现这个目标吗?
这是我的样式代码:
<Style TargetType="{x:Type PasswordBox}" x:Key="Password">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="PasswordBox">
<Grid>
<PasswordBox Background="{StaticResource BrushDark}" Foreground="{StaticResource BrushTextNormal}" BorderBrush="{StaticResource BrushBorderInput}" BorderThickness="1"/>
<TextBlock HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="Password"
Margin="5,0,5,0"
Foreground="#ff808080"
IsHitTestVisible="False"
x:Name="UserMessage"
Visibility="Hidden"/>
<!--<ScrollViewer Foreground="{StaticResource BrushTextNormal}" Background="{StaticResource BrushTextNormal}" x:Name="PART_ContentHost"/>-->
<!--<Decorator TextBlock.Foreground="White" x:Name="PART_ContentHost"/>-->
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Tag" Value=""/>
<Condition Property="IsKeyboardFocusWithin" Value="False"/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" TargetName="UserMessage" Value="Visible"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
如果您为 PasswordBox
或 TextBox
创建自定义 ControlTemplate
,您需要将 ScrollViewer
命名为 x:Name="PART_ContentHost
而不是内部 PasswordBox
来自PasswordBox Syles and Templates
PART_ContentHost - A visual element that can contain a FrameworkElement. The text of the PasswordBox is displayed in this element.
并把Foreground
变成你Style
中的另一个Setter
。另外,作为侧节点,我会对 Background
做同样的事情,并在你的 ControlTemplate
中使用 TemplateBinding
。这将提供更大的灵活性,并允许您手动更改 Background
and/or Foreground
而无需更改 ControlTemplate
<Style TargetType="{x:Type PasswordBox}" x:Key="Password">
<Setter Property="Foreground" Value="{StaticResource BrushTextNormal}" />
<Setter Property="Background" Value="{StaticResource BrushDark}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type PasswordBox}">
<Grid Background="{TemplateBinding Background}">
<ScrollViewer x:Name="PART_ContentHost" .../>
<TextBlock .../>
</Grid>
<ControlTemplate.Triggers>
<!-- removed -->
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
我目前正在尝试执行以下操作: 如果未输入密码,则应显示文本 "Password"。
但是我的模板没有显示密码,如果我使用装饰器或滚动查看器,我无法更改文本的颜色。
你有什么想法来实现这个目标吗?
这是我的样式代码:
<Style TargetType="{x:Type PasswordBox}" x:Key="Password">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="PasswordBox">
<Grid>
<PasswordBox Background="{StaticResource BrushDark}" Foreground="{StaticResource BrushTextNormal}" BorderBrush="{StaticResource BrushBorderInput}" BorderThickness="1"/>
<TextBlock HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="Password"
Margin="5,0,5,0"
Foreground="#ff808080"
IsHitTestVisible="False"
x:Name="UserMessage"
Visibility="Hidden"/>
<!--<ScrollViewer Foreground="{StaticResource BrushTextNormal}" Background="{StaticResource BrushTextNormal}" x:Name="PART_ContentHost"/>-->
<!--<Decorator TextBlock.Foreground="White" x:Name="PART_ContentHost"/>-->
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Tag" Value=""/>
<Condition Property="IsKeyboardFocusWithin" Value="False"/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" TargetName="UserMessage" Value="Visible"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
如果您为 PasswordBox
或 TextBox
创建自定义 ControlTemplate
,您需要将 ScrollViewer
命名为 x:Name="PART_ContentHost
而不是内部 PasswordBox
来自PasswordBox Syles and Templates
PART_ContentHost - A visual element that can contain a FrameworkElement. The text of the PasswordBox is displayed in this element.
并把Foreground
变成你Style
中的另一个Setter
。另外,作为侧节点,我会对 Background
做同样的事情,并在你的 ControlTemplate
中使用 TemplateBinding
。这将提供更大的灵活性,并允许您手动更改 Background
and/or Foreground
而无需更改 ControlTemplate
<Style TargetType="{x:Type PasswordBox}" x:Key="Password">
<Setter Property="Foreground" Value="{StaticResource BrushTextNormal}" />
<Setter Property="Background" Value="{StaticResource BrushDark}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type PasswordBox}">
<Grid Background="{TemplateBinding Background}">
<ScrollViewer x:Name="PART_ContentHost" .../>
<TextBlock .../>
</Grid>
<ControlTemplate.Triggers>
<!-- removed -->
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>