简体   繁体   English

使用文本框作为密码框,并在 wpf 中设置密码字符

[英]Using a textbox as a passwordbox with a password char set in wpf

I'm having trouble trying to setup a textbox with a password char AND a placeholder.我在尝试使用密码字符和占位符设置文本框时遇到问题。 I've already done one for the username and that works fine but I'm stumpt over what I can do with the passwordbox.我已经为用户名做了一个,效果很好,但我对密码框能做什么感到困惑。

I know you can have a passwordbox with the password char but you can't have a placeholder as well in wpf.我知道你可以有一个带有密码字符的密码框,但你不能在 wpf 中也有一个占位符。

I have this for the username, I want the same done for the passwordbox:我有这个用户名,我想对密码框做同样的事情:

this.usernameTxt.Foreground = Brushes.LightGray;

        this.usernameTxt.Text = "Username";

this.usernameTxt.GotKeyboardFocus += new KeyboardFocusChangedEventHandler(this.usernameTxt_Selected);

this.usernameTxt.PreviewLostKeyboardFocus += new KeyboardFocusChangedEventHandler(this.usernameTxt_Lostfocus);

public void usernameTxt_Lostfocus(object sender, EventArgs e)
    {
        if (string.IsNullOrEmpty(usernameTxt.Text))
                    {
                        this.usernameTxt.Text = "Username";
                        this.usernameTxt.Foreground = Brushes.LightGray;
                    }
    }

    public void usernameTxt_Selected(object sender, EventArgs e)
    {
            this.usernameTxt.Focus();
            this.usernameTxt.SelectAll();
            this.usernameTxt.Text = "";
            this.usernameTxt.Foreground = Brushes.Black;
    }

Here's a workaround that you can review. 您可以查看以下变通办法。 In this example, I rely on the TextChanged event of my textbox control that's embedded within the password control. 在此示例中,我依靠嵌入在密码控件中的文本框控件的TextChanged事件。

When the TextChanged event is triggered, I use a stack to capture the last character entered and then I maintain within my view-model an obfuscated password as well as an actual password. 触发TextChanged事件时,我使用堆栈来捕获最后输入的字符,然后在视图模型中维护一个混淆的密码以及一个实际的密码。 When the delete or back key is pressed, I pop the last character entered off the stack. 当按下删除或返回键时,我弹出从堆栈中输入的最后一个字符。

XAML: XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        xmlns:converters="clr-namespace:WpfApplication1.Converters"
        Title="MainWindow" Height="350" Width="525">

    <Window.DataContext>
        <local:ViewModel />
    </Window.DataContext>
    <Grid>
        <PasswordBox x:Name="passwordBox" Height="20" PasswordChar="*" Width="200" Background="LightYellow" >
            <PasswordBox.Template>
                <ControlTemplate>
                    <TextBox x:Name="PasswordTextbox" GotFocus="GotFocus" Text="{Binding ObfuscatedPassword, Mode=TwoWay}" KeyUp="PasswordTextbox_KeyUp" TextAlignment="Center" Foreground="LightGray" />
                </ControlTemplate>
            </PasswordBox.Template>
        </PasswordBox>
    </Grid>
</Window>

View-model: 视图模型:

namespace WpfApplication1
{
    public class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string obfuscatedPassword = "user name";

        public string ObfuscatedPassword
        {
            get { return obfuscatedPassword; }
            set 
            { 
                if (this.obfuscatedPassword != value)
                {
                    this.obfuscatedPassword = value;
                    OnPropertyChanged();
                }
            }
        }

        private string actualPassword = null;
        public string ActualPassword
        {
            get { return actualPassword; }
            set
            {
                if (this.actualPassword != value)
                {
                    this.actualPassword = value;
                    OnPropertyChanged();
                }
            }
        }

        private void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Code-behind: 后台代码:

public partial class MainWindow : Window
{
    ViewModel viewModel = null;
    public MainWindow()
    {
        InitializeComponent();

        this.viewModel = this.DataContext as ViewModel;
    }

    public string defaultText = "user name";

    Stack<string> charStack = new Stack<string>();


    private void PasswordTextbox_KeyUp(object sender, KeyEventArgs e)
    {
        var textbox = sender as TextBox;
        textbox.Text = string.Empty;

        var key = e.Key.ToString();

        if (this.viewModel.ObfuscatedPassword == defaultText)
        {
            this.viewModel.ObfuscatedPassword = string.Empty;
        }

        var deleteLastCharacter = (e.Key == Key.Delete || e.Key == Key.Back);

        if (deleteLastCharacter)
        {

            if (charStack.Count > 0)
            {
                charStack.Pop();
            }

            if (charStack.Count == 0)
            {
                textbox.Text = defaultText;
                textbox.CaretIndex = defaultText.Length;
                textbox.SelectAll();
                e.Handled = true;
                return;
            }
        }
        else if (IsTextAllowed(key))
        {
            charStack.Push(key);
        }
        else
        {
            e.Handled = true;
            return;
        }

        this.viewModel.ObfuscatedPassword = ObfuscatePassword();
        this.viewModel.ActualPassword = ActualizePassword();

        textbox.CaretIndex = this.viewModel.ObfuscatedPassword.Length;
        e.Handled = true;
    }

    private static bool IsTextAllowed(string text)
    {
        Regex regex = new Regex(@"^.*(?=.{10,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$"); //regex that matches disallowed text
        return !regex.IsMatch(text);
    }

    private string ActualizePassword()
    {
        var password = string.Empty;

        foreach (var character in charStack.Reverse())
        {
            password += character;
        }

        return password;
    }

    private string ObfuscatePassword()
    {
        var password = string.Empty;

        foreach (var character in charStack.Reverse())
        {
            password += passwordBox.PasswordChar;
        }

        return password;
    }

    private void GotFocus(object sender, RoutedEventArgs e)
    {
        if (this.viewModel.ObfuscatedPassword == defaultText)
        {
            this.viewModel.ObfuscatedPassword = string.Empty;
        }
    }

}

First download password dot font from this link , https://github.com/davidagraf/passwd/blob/master/public/ttf/password.ttf首先从这个链接下载密码点字体, https://github.com/davidagraf/passwd/blob/master/public/ttf/password.ttf

Add folder named "AppFonts" under this put password.ttf file and add reference of this font to your WPF application App.xaml.在此 put password.ttf 文件下添加名为“AppFonts”的文件夹,并将此字体的引用添加到您的 WPF 应用程序 App.xaml。 So globally you can access this font.因此,您可以在全球范围内访问此字体。

<Application.Resources>
        <ResourceDictionary>            
            <Style x:Key="CustomFont">                
                <Setter Property="TextElement.FontFamily" Value="/AppFonts/#password"></Setter>
            </Style>
        </ResourceDictionary>
    </Application.Resources>

Create a PasswordViewModel and download nuget package MvvmLight of GalaSoft.创建 PasswordViewModel 并下载 GalaSoft 的 nuget 包 MvvmLight。

using System;
using GalaSoft.MvvmLight;

public class PasswordViewModel : ViewModelBase
    {
     private string _PlainPassword { get; set; }
     public string PlainPassword
        {
            get { 
               
                return _PlainPassword; 
            }
            set
            {
                _PlainPassword = value;
                RaisePropertyChanged("Password");
            }
        }
}

now create your view PasswordUserControl.xaml and view constructor add view model to DataContext.现在创建您的视图 PasswordUserControl.xaml 并将视图构造函数添加到 DataContext。

  PasswordViewModel passwordModel= new PasswordViewModel();
  this.DataContext = passwordModel;

and in view xaml paste this并在查看 xaml 粘贴此

<Grid  Margin="20,0,15,0" Height="45">
              
                <TextBox Grid.Row="3" Name="txtPasswordEntry" Background="Transparent" Padding="12" Foreground="#787878" Height="45" 
                Text="{Binding PlainPassword,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" 
                FontFamily="/WpfApplication;component/AppFonts/#Password" FontSize="14" FontWeight="Medium">
                    <TextBox.InputBindings>
                        <!--Disable CTRL+C (COPY) -->
                        <KeyBinding Command="ApplicationCommands.NotACommand" Key="C" Modifiers="Control" />
                        <!--Disable CTRL+X (CUT) -->
                        <KeyBinding Command="ApplicationCommands.NotACommand" Key="X" Modifiers="Control" />
                    </TextBox.InputBindings>
                    <TextBox.ContextMenu>
                        <!--Hide context menu where you could copy/cut as well -->
                        <ContextMenu Visibility="Collapsed" />
                    </TextBox.ContextMenu>
                </TextBox>
                <TextBlock IsHitTestVisible="False" Padding="13" Text="Password" Foreground="#787878" Height="45" FontSize="14" FontWeight="Medium">
                <TextBlock.Style>
                    <Style TargetType="{x:Type TextBlock}">
                        <Setter Property="Visibility" Value="Collapsed"/>
                        <Style.Triggers>
                                <DataTrigger Binding="{Binding Text, ElementName=txtPasswordEntry}" Value="">
                                <Setter Property="Visibility" Value="Visible"/>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </TextBlock.Style>
            </TextBlock>
            </Grid>

Note: Hear FontFamily="/WpfApplication;component/AppFonts/#Password" WpfApplication is your Application Name.注意:听到 FontFamily="/WpfApplication;component/AppFonts/#Password" WpfApplication 是您的应用程序名称。 Or you can change font family from textbox property.或者您可以从文本框属性更改字体系列。

Now run the app .现在运行应用程序。 See password box has a place holder text Password and write your password it will disappear.请参阅密码框有一个占位符文本密码并输入您的密码它将消失。 Also its secure you can't copy cut of this password.而且它是安全的,你不能复制这个密码。 在此处输入图像描述

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

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