繁体   English   中英

为什么我的WPF PasswordBox样式触发不起作用?

[英]Why is my WPF PasswordBox style trigger not working?

所以我在我的应用程序中有这个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.Password清除后,PasswordBox禁用正在发生。 所以这应该不重要[我猜]。 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代码中解决它。

链接到项目: HERE - 必须下载!

我决定为您提供一个完整的MVVM示例,以便您可以“以正确的方式”学习如何做到这一点。

注意:我正在使用MVVM Light (因为它的RelayCommand)。 您可以通过NuGet安装它。 它值得拥有,因为它为MVVM开发提供了许多有用的类。 另一种替代方案是棱镜

1.什么是MVVM?

MVVM(Model - View - ViewModel)是一种编程模式,与WPF完美配合。 它的主要目的是从ViewModels中分离视图 - 您所看到的 - 您的程序的逻辑。

它可以导致需要更多的编码,但是收益很高 - 你得到一个干净的,结构化的代码,模块化和非常容易测试(即单元测试)。

1.1 - 模型

模型基本上是程序的结构。 它应该为您的类提供支持数据的主干,并在ViewModels中进一步使用。

在这个项目的情况下 - 虽然没有模型 - 因为它不需要(当你继续申请时肯定会需要它!)

1.2 - 查看

View基本上就是你所看到的。 通常它是一个窗口,它有显示的元素 - 但它不一定只是那个! UserControl本身可以是一个View,并且它拥有自己的ViewModel - 与它所在的Window不同。

1.3 ViewModel

ViewModel基本上是程序的核心。 它保存逻辑并具有属性,View可以绑定到其控件中并使用/显示它们。 考虑一下你的应用程序的brain

2.代码

视图:

<Window x:Class="PasswordBoxMVVM.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:PasswordBoxMVVM"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:b="clr-namespace:System.Media;assembly=System"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <local:PasswordLengthToColorConverter x:Key="passwordLengthToColorConverter" />
</Window.Resources>
<Grid>
    <StackPanel VerticalAlignment="Center">
        <PasswordBox local:PasswordBoxMVVMAttachedProperties.EncryptedPassword="{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                     IsEnabled="{Binding Path=IsPasswordFieldDisabled, Mode=TwoWay ,UpdateSourceTrigger=PropertyChanged}"
                     FontSize="20" Width="384" Height="34" PasswordChar="█" HorizontalAlignment="Center" FontFamily="Century Gothic" 
                     HorizontalContentAlignment="Left" VerticalContentAlignment="Center" TabIndex="2" Foreground="Red"
                     PasswordChanged="MyPasswordBox_PasswordChanged"
                     IsEnabledChanged="PasswordBox_IsEnabledChanged">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="PasswordChanged">
                    <i:InvokeCommandAction Command="{Binding Path=PasswordChangedCommand}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <PasswordBox.Style>
                <Style TargetType="{x:Type PasswordBox}">
                    <Setter Property="Background" Value="#FFCCCCCC" />
                    <Setter Property="BorderThickness" Value="0,2,0,2" />
                    <Setter Property="BorderBrush" Value="Red" />
                    <Setter Property="ClipToBounds" Value="true"/>
                    <Setter Property="OverridesDefaultStyle" Value="true"/>
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="PasswordBox">
                                <Grid>
                                    <Border Background="{TemplateBinding Background}"
                                            BorderThickness="{TemplateBinding BorderThickness}"
                                            BorderBrush="{TemplateBinding Foreground}">
                                        <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"  Opacity="0.3" Foreground="Gray">
                                    </TextBlock>
                                </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>

                                    <DataTrigger Binding="{Binding Path=IsPasswordFieldEmpty,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Value="false">
                                        <Setter TargetName="TB" Property="Text" Value="Password:" />
                                        <DataTrigger.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>
                                        </DataTrigger.EnterActions>
                                        <DataTrigger.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>
                                        </DataTrigger.ExitActions>
                                    </DataTrigger>

                                    <MultiDataTrigger>
                                        <MultiDataTrigger.Conditions>
                                            <Condition Binding="{Binding Path=IsFocused, RelativeSource={RelativeSource Self}}" Value="false" />
                                            <Condition Binding="{Binding Path=IsPasswordFieldEmpty, UpdateSourceTrigger=PropertyChanged}" Value="true" />
                                        </MultiDataTrigger.Conditions>
                                        <Setter TargetName="TB" Property="Text" Value="Password" />
                                        <MultiDataTrigger.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>
                                        </MultiDataTrigger.EnterActions>
                                        <MultiDataTrigger.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>
                                        </MultiDataTrigger.ExitActions>
                                    </MultiDataTrigger>

                                    <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="Gray"/>
                                        <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.Triggers>
                <EventTrigger RoutedEvent="PasswordBox.PasswordChanged">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Storyboard.TargetProperty="(PasswordBox.Foreground).(SolidColorBrush.Color)" 
                                            To="{Binding Path=Password.Length, UpdateSourceTrigger=PropertyChanged, 
                                            Converter={StaticResource passwordLengthToColorConverter}}" Duration="0:0:0.1">
                            </ColorAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
                <EventTrigger RoutedEvent="local:PasswordBoxAttachedEvent.HasBeenDisabled">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Storyboard.TargetProperty="(PasswordBox.Foreground).(SolidColorBrush.Color)" 
                                            To="Gray" Duration="0:0:0.1">
                            </ColorAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
                <EventTrigger RoutedEvent="local:PasswordBoxAttachedEvent.HasBeenEnabled">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Storyboard.TargetProperty="(PasswordBox.Foreground).(SolidColorBrush.Color)" 
                                            To="{Binding Path=Password.Length, UpdateSourceTrigger=PropertyChanged, 
                                            Converter={StaticResource passwordLengthToColorConverter}}" Duration="0:0:0.1">
                            </ColorAnimation>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </PasswordBox.Triggers>
        </PasswordBox>
        <Button Width="200" Height="50" Margin="0,50,0,0" Command="{Binding Path=ClickCommand}">Click me</Button>
    </StackPanel>
</Grid>

这与你提供的内容没什么不同,但它已经被改成MVVM - 绑定,命令和转换器被添加。 他们需要绑定(连接)我们的ViewViewModel

View的代码背后:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        var vm = new PasswordViewModel();
        this.DataContext = vm;

        InitializeComponent();
    }

    private void MyPasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
    {
        PasswordBox pBox = sender as PasswordBox;
        PasswordBoxMVVMAttachedProperties.SetEncryptedPassword(pBox, pBox.SecurePassword);    
    }

    private void PasswordBox_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        PasswordBox pBox = sender as PasswordBox;

        if (pBox.IsEnabled == false)
        {
            RoutedEventArgs eventArgs = new RoutedEventArgs(PasswordBoxAttachedEvent.HasBeenDisabledEvent);
            pBox.RaiseEvent(eventArgs);
        }
        if (pBox.IsEnabled == true)
        {
            RoutedEventArgs eventArgs = new RoutedEventArgs(PasswordBoxAttachedEvent.HasBeenEnabledEvent);
            pBox.RaiseEvent(eventArgs);
        }
    }
}

在View的构造函数中,我们定义了ViewModel - 并将其设置为View的DataContext

下面是一些事件处理程序,它们允许我们附加事件和属性 - 但稍后我们将讨论这个问题。

重要提示:当您继续自己开始学习MVVM时,您可能会看到人们说“在良好的MVVM中,View中应该没有代码隐藏”。 这实际上是完全公牛**它是完全没有把代码隐藏在View中,只要它不违反任何MVVM原则 - 而且通常,它使得编写一些东西更容易一些。

ViewModel:

namespace PasswordBoxMVVM
{
    public class PasswordViewModel : ViewModelBase
    {
        private bool isPasswordFieldEmpty;
        public bool IsPasswordFieldEmpty
        {
            get { return isPasswordFieldEmpty; }
            set
            {
                isPasswordFieldEmpty = value;
                RaisePropertyChanged();
            }
        }

        private SecureString password;
        public SecureString Password
        {
            get { return password; }
            set
            {
                password = value;
                RaisePropertyChanged();
            }
        }

        private bool isPassWordFieldDisabled;
        public bool IsPasswordFieldDisabled
        {
            get { return isPassWordFieldDisabled; }
            set
            {
                isPassWordFieldDisabled = value;
                RaisePropertyChanged();
            }
        }

        public ICommand ClickCommand { get { return new RelayCommand(doAction, canDoAction); } }
        public ICommand PasswordChangedCommand { get { return new RelayCommand(updatePassword, canUpdatePassword); } }

        public PasswordViewModel()
        {
            // Init conditions, need them to not get null reference at the start.
            isPassWordFieldDisabled = true;
            IsPasswordFieldEmpty = true;
        }

        private void doAction()
        {
            IsPasswordFieldDisabled = !IsPasswordFieldDisabled;
        }

        private bool canDoAction()
        {
            // Replace this with any condition that you need.
            return true;
        }

        private void updatePassword()
        {
            if (Password != null)
            {
                if (Password.Length > 0)
                {
                    isPasswordFieldEmpty = false;
                }
                else
                {
                    isPasswordFieldEmpty = true;
                }
            }
            else
            {
                isPasswordFieldEmpty = true;
            }
        }

        private bool canUpdatePassword()
        {
            // Replace this with any condition that you need. 
            return true;
        }
    }
}

这里有很多事情要发生。 首先,我们有一些公共属性,如Password,isPasswordFieldDisabled等。这些是我们的View可以绑定的属性,它允许我们从ViewModel控制View。

我们还有命令,这是View与ViewModel交互的一种方式。 View将某些事物绑定到这些命令(如事件),然后我们根据ViewModel中的代码执行代码。

在这个例子中,单击按钮会向我们的ViewModel发出一个命令,该命令会更改isPasswordBoxDisabled属性,即我们的PasswordBox isEnabled属性被绑定 - 实际上,启用/禁用PasswordBox,而View和ViewModel之间没有任何DIRECT交互! 很酷,对吧?

变流器

namespace PasswordBoxMVVM
{
    class PasswordLengthToColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            int length = (int)value;
            Color output = Colors.Red;

            if (length >= 0 && length < 5)
                output = Colors.Red;

            else if (length >= 5 && length < 6)
                output = Colors.Orange;

            else if (length >= 6 && length < 7)
                output = Colors.Yellow;

            else if (length >= 7 && length < 8)
                output = Colors.LightGreen;

            else if (length >= 8)
                output = Colors.Green;

            return output;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
}

转换器很像翻译器。 在这里,我们将密码长度转换为颜色 - 以便我们以后可以在动画中使用它们。 当我说MVVM是模块化的时候,这是我的意思的完美例子 - 你想要不同的转换? 只需将绑定绑定到新转换器即可完成,无需重写View!

密码附加属性 - 查看链接项目

这仅仅是因为我们需要将PasswordBox的密码绑定到ViewModel。 最初,PasswordBox不支持。 输入附加属性! 它允许“扩展”我们PasswordBox的可能性,通过附加(因此名称)一个新属性 - 我们可以绑定到我们的ViewModel。

附加事件也是如此 - 您可以在代码中找到其他所有内容,因为字符配额限制我粘贴更多内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM