It occurred to me that a regular text box control with a custom font would work as long as I prevented cut and paste operations on it. For the purpose of this demonstration I also limit the password to digits because that's the requirement I have to satisfy for my current project.
Let's start off by creating a new WPF application project called "Password".
I got my font from https://github.com/davidagraf/passwd/blob/master/public/ttf/password.ttf, thank you David. Create a folder in the project called Fonts and drop the ttf file into the folder. Make sure Build Action = Resource and Copy to Output Directory = Do not copy.
I'm going to show you a window with several components. The interesting one is the TextBox. The FontFamily path is important to get right. The PreviewExecuted event handler suppresses edit keyboard shortcuts, the PreviewKeyDown suppresses non digit key presses, and the ContextMenu suppresses the text box's default context sensitive menu (because it contains shortcuts to edit commands).
<Window x:Class="Password.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:Password"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<StackPanel Orientation="Horizontal" Height="20">
<TextBlock Text="Password:
"/>
<TextBox FontFamily="pack://application:,,,/Fonts/#Password" Text="{Binding Password, UpdateSourceTrigger=PropertyChanged}"
Width="100" CommandManager.PreviewExecuted="TextBox_PreviewExecuted" PreviewKeyDown="TextBox_PreviewKeyDown"
ContextMenu="{x:Null}" MaxLength="6"/>
<TextBlock Text="{Binding Password}" Margin="10,0,0,0"/>
</StackPanel>
</Window>
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
namespace Password
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
private String _Password;
public String Password
{
get { return
_Password; }
set
{
if (!value.Equals(_Password))
{
_Password = value;
NotifyPropertyChanged("Password");
}
}
}
public MainWindow()
{
InitializeComponent();
}
public event PropertyChangedEventHandler
PropertyChanged;
private void
NotifyPropertyChanged(String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private void
TextBox_PreviewExecuted(object sender, ExecutedRoutedEventArgs e)
{
// Suppress
copy and paste
if (e.Command == ApplicationCommands.Cut ||
e.Command == ApplicationCommands.Copy ||
e.Command == ApplicationCommands.Paste)
e.Handled = true;
}
private void
TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
// Allow cursor
movement and backspace
if (e.Key == Key.Back ||
e.Key == Key.Left || e.Key == Key.Right)
return;
String c = e.Key.ToString().Replace("NumPad", "").Replace("D", "");
// Suppress any
keypress that is not a digit
if (c.Length != 1)
e.Handled = true;
else
if (!char.IsDigit(Convert.ToChar(c)))
e.Handled = true;
}
}
}
No comments:
Post a Comment