【发布时间】:2017-10-02 15:02:35
【问题描述】:
所以我的应用中有这个 PasswordBox。
XAML
<PasswordBox Name="PB_PASSWORD" Padding="100,0,34,0" FontSize="20" Width="384" Height="34" PasswordChar="█" Password="" HorizontalAlignment="Left" VerticalAlignment="Top" FontFamily="Century Gothic" HorizontalContentAlignment="Left" VerticalContentAlignment="Center" TabIndex="2" PasswordChanged="PB_PASSWORD_PasswordChanged" >
<PasswordBox.Style>
<Style BasedOn="{x:Null}" TargetType="{x:Type PasswordBox}">
<Setter Property="Background" Value="#FFCCCCCC" />
<Setter Property="Foreground" Value="#FFF22613" />
<Setter Property="BorderBrush" Value="#FFF22613" />
<Setter Property="BorderThickness" Value="0,2,0,2" />
<Setter Property="ClipToBounds" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="PasswordBox">
<Grid>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer x:Name="PART_ContentHost" Margin="0,-4,0,0" />
</Border>
<TextBlock Name="TB" Text="Password" HorizontalAlignment="Left" Margin="140,0,0,0" VerticalAlignment="Center" Foreground="#FF222222" Opacity="0.3"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="true">
<Setter TargetName="TB" Property="Text" Value="Password:" />
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Storyboard.TargetProperty="Padding" To="100,0,34,0" Duration="0:0:0.3">
<ThicknessAnimation.EasingFunction>
<SineEase EasingMode="EaseOut"/>
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
<ThicknessAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Margin" To="2,0,0,0" Duration="0:0:0.3">
<ThicknessAnimation.EasingFunction>
<SineEase EasingMode="EaseOut"/>
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
<DoubleAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.3">
<DoubleAnimation.EasingFunction>
<SineEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Storyboard.TargetProperty="Padding" To="230,0,0,0" Duration="0:0:0.3">
<ThicknessAnimation.EasingFunction>
<BackEase EasingMode="EaseOut"/>
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
<ThicknessAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Margin" To="140,0,0,0" Duration="0:0:0.3">
<ThicknessAnimation.EasingFunction>
<BackEase EasingMode="EaseOut"/>
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
<DoubleAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Opacity" To="0.3" Duration="0:0:0.3">
<DoubleAnimation.EasingFunction>
<BackEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="ClipToBounds" Value="false">
<Setter TargetName="TB" Property="Text" Value="Password:" />
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Storyboard.TargetProperty="Padding" To="100,0,34,0" Duration="0:0:0.3">
<ThicknessAnimation.EasingFunction>
<SineEase EasingMode="EaseOut"/>
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
<ThicknessAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Margin" To="2,0,0,0" Duration="0:0:0.3">
<ThicknessAnimation.EasingFunction>
<SineEase EasingMode="EaseOut"/>
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
<DoubleAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.3">
<DoubleAnimation.EasingFunction>
<SineEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Storyboard.TargetProperty="Padding" To="230,0,0,0" Duration="0:0:0.3">
<ThicknessAnimation.EasingFunction>
<BackEase EasingMode="EaseOut"/>
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
<ThicknessAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Margin" To="140,0,0,0" Duration="0:0:0.3">
<ThicknessAnimation.EasingFunction>
<BackEase EasingMode="EaseOut"/>
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
<DoubleAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Opacity" To="0.3" Duration="0:0:0.3">
<DoubleAnimation.EasingFunction>
<BackEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused" Value="false" />
<Condition Property="ClipToBounds" Value="true" />
</MultiTrigger.Conditions>
<Setter TargetName="TB" Property="Text" Value="Password" />
<MultiTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Storyboard.TargetProperty="Padding" To="230,0,0,0" Duration="0:0:0.3">
<ThicknessAnimation.EasingFunction>
<BackEase EasingMode="EaseOut"/>
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
<ThicknessAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Margin" To="140,0,0,0" Duration="0:0:0.3">
<ThicknessAnimation.EasingFunction>
<BackEase EasingMode="EaseOut"/>
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
<DoubleAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Opacity" To="0.3" Duration="0:0:0.3">
<DoubleAnimation.EasingFunction>
<BackEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
<MultiTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Storyboard.TargetProperty="Padding" To="100,0,34,0" Duration="0:0:0.3">
<ThicknessAnimation.EasingFunction>
<SineEase EasingMode="EaseOut"/>
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
<ThicknessAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Margin" To="2,0,0,0" Duration="0:0:0.3">
<ThicknessAnimation.EasingFunction>
<SineEase EasingMode="EaseOut"/>
</ThicknessAnimation.EasingFunction>
</ThicknessAnimation>
<DoubleAnimation Storyboard.TargetName="TB" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.3">
<DoubleAnimation.EasingFunction>
<SineEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</MultiTrigger.ExitActions>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="TB" Property="Text" Value="DISABLE"/>
<Setter TargetName="TB" Property="Margin" Value="140,0,0,0"/>
<Setter Property="Background" Value="#FFAAAAAA"/>
<Setter Property="Foreground" Value="#FF777777"/>
<Setter Property="BorderBrush" Value="#FF888888" />
<Setter Property="BorderThickness" Value="0,3,0,3" />
</Trigger>
<Trigger Property="Tag" Value="ShowPW">
<Setter Property="Visibility" Value="Hidden"/>
</Trigger>
<Trigger Property="Tag" Value="HidePW">
<Setter Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
</Style.Triggers>
</Style>
</PasswordBox.Style>
</PasswordBox>
而且我需要在输入的密码为空时更改它的边框颜色。
如果 PasswordBox 的密码值发生更改,BorderColor 会发生以下代码更改。
注意:PasswordBox 禁用是在 PasswordBox.Password 被清除后发生的。所以这不应该重要[我猜]。
c#
private void PB_PASSWORD_PasswordChanged(object sender, RoutedEventArgs e)
{
if (PB_PASSWORD.SecurePassword.Length == 0)
{ //Password is Empty.
PB_PASSWORD.ClipToBounds = true;
}
else
{ //Password Not Empty
PB_PASSWORD.ClipToBounds = false;
}
Int32 PWStrength = 0;
if (PB_PASSWORD.SecurePassword.Length >= 5)
{
//A Function that Return int Value between 0-5 depending on how Strong is Password.
PWStrength = GetPasswordStrength(Marshal.PtrToStringUni(Marshal.SecureStringToGlobalAllocUnicode(PB_PASSWORD.SecurePassword)));
}
//Corresponding Colors Are Set as per Returned Integer0=red, 1=Orange+Red, 2=Orange, 3=Yellow, 4=Light Green, 5=Green
switch (PWStrength)
{
case 0:
{
//Following 2 Lines Required to Unfreez Color From Control
PB_PASSWORD.Foreground = new SolidColorBrush(CustomColors.PasswordStrengthColors[PWStrength]);
PB_PASSWORD.BorderBrush = new SolidColorBrush(CustomColors.PasswordStrengthColors[PWStrength]);
ColorAnimation AnimateForegroundColor_0 = new ColorAnimation(CustomColors.PasswordStrengthColors[PWStrength], new Duration(TimeSpan.FromMilliseconds(200)));
PB_PASSWORD.Foreground.BeginAnimation(SolidColorBrush.ColorProperty, AnimateForegroundColor_0);
ColorAnimation AnimateBorderBrushColor_0 = new ColorAnimation(CustomColors.PasswordStrengthColors[PWStrength], new Duration(TimeSpan.FromMilliseconds(200)));
PB_PASSWORD.BorderBrush.BeginAnimation(SolidColorBrush.ColorProperty, AnimateBorderBrushColor_0);
break;
}
default:
{
ColorAnimation AnimateForegroundColor = new ColorAnimation(CustomColors.PasswordStrengthColors[PWStrength], new Duration(TimeSpan.FromMilliseconds(200)));
PB_PASSWORD.Foreground.BeginAnimation(SolidColorBrush.ColorProperty, AnimateForegroundColor);
ColorAnimation AnimateBorderBrushColor = new ColorAnimation(CustomColors.PasswordStrengthColors[PWStrength], new Duration(TimeSpan.FromMilliseconds(200)));
PB_PASSWORD.BorderBrush.BeginAnimation(SolidColorBrush.ColorProperty, AnimateBorderBrushColor);
break;
}
}
}
密码值不可访问,所以我使用了ClipToBounds布尔值来设置它,如下所示:
C#
if (String.IsNullOrEmpty(PB_PASSWORD.Password))
{ PB_PASSWORD.ClipToBounds = true; }
else
{ PB_PASSWORD.ClipToBounds = false; }
当应用程序首次启动时,这工作正常。
当我从代码隐藏中修改启用/禁用值时,问题就开始了,如下所示:
C#
private void Button_Click(object sender, RoutedEventArgs e)
{
if (PB_PASSWORD.IsEnabled)
{
PB_PASSWORD.ClipToBounds = true;
PB_PASSWORD.Password = "";
BTN_BROWSE.Focus();
PB_PASSWORD.MoveFocus(new System.Windows.Input.TraversalRequest(System.Windows.Input.FocusNavigationDirection.Next));
PB_PASSWORD.IsEnabled = false;
}
else
{
PB_PASSWORD.IsEnabled = true;
}
}
在输入密码然后禁用后应该是这样的:
但它看起来像这样:
我需要在 XAML 代码中解决它。
【问题讨论】:
-
我认为问题不在于发布的代码中的任何地方。我将它全部复制到一个示例项目中,对我来说 - 一切都如你所描述的那样工作。请显示所有与密码框有关的代码。此外,永远不要使用控件自己的 DP 作为您自己的值的占位符。您应该在您的 VM 中创建一个属性,然后读取/写入它,而不是写入 ClipToBounds。
-
用代码更新。我认为这会引起注意,因为在 PasswordBox.Password 被清除后会发生禁用。另外,您能否向我解释一下如何创建自己的财产或提供指导。它会在很多方面帮助我..
-
这个控件后面没有ViewModel吗?为什么要这样工作? PasswordStrength 应该是 ViewModel 上的计算属性,唯一需要发生的事情是将实例的 BorderBrush 和 Foreground 绑定到 PasswordStrength,并使用转换器返回颜色。你所拥有的只是错误的,之后很难维护。
-
@Mishka 确实似乎没有任何 ViewModel。一切都应该转移到 ViewModel 并使用绑定和命令进行管理(除了密码,最好的方法(即使它违反 MVVM)是从控件的 CLR 属性中实际获取它,就像他所做的那样。
-
我只是在学习基础知识,现在别让我太难,现在我必须在 Google 上搜索如何使用 MVVM :P... 我只需要回答为什么我的代码不工作...之后我会找出 MVVM :)
标签: c# wpf templates triggers styles