WPF實現(xiàn)授權(quán)碼顯示密文并支持換行
WPF 授權(quán)碼顯示密文并支持換行
- 框架使用
.NET8
; Visual Studio 2022
;
有開發(fā)者需要制作一個授權(quán)碼輸入框輸入內(nèi)容后顯示密文并且能 Enter
進行換行輸入。由于無法使用 PasswordBox
控件本身不支持換行,因為它設(shè)計為單行輸入控件。
所以最簡單的方法是使用 TextBox
并通過自定義邏輯代碼來掩蓋輸入的文本。這樣可以實現(xiàn)多行輸入,處理文本顯示和密碼掩碼的邏輯。
接下來我們自定義一個控件 MultiLinePasswordBox
繼承 TextBox
輸入字符會以密碼字符(如默認的 ●
)顯示。
私有字段如下:
- passwordBuilder 用于存儲密碼。
- previousText 用于存放上一次的文本。
- isUpdating 用于記錄是否正在編輯。
依賴屬性如下:
- PasswordChar:用于顯示密碼字符的字符,如果未顯示則默認為
●
。 - PlainText:控件中原始的未掩蓋的文本。
構(gòu)造函數(shù):
- 設(shè)置 TextWrapping = TextWrapping.Wrap; 支持多行顯示。
- 設(shè)置 AcceptsReturn = true 支持按下
Enter
換行。 - 訂閱 TextChanged 事件,文本更改時將輸入的文本轉(zhuǎn)換為密碼掩碼,如果 isUpdating 的標(biāo)志為 true ,則直接返回,避免重復(fù)更新文本。
- 計算當(dāng)前輸入文本和上一次文本之間的長度差異,如果長度是正數(shù)則插入,反之長度差異是負數(shù)則刪除。
- 調(diào)用 CreateMaskedTextWithLineBreaks 方法創(chuàng)建帶有掩碼和換行符的文本。
- 更新控件的文本,保持光標(biāo)位置不變,并更新PlainText。
1)MultiLinePasswordBox.cs
代碼如下:
using System; using System.Diagnostics; using System.Text; using System.Windows; using System.Windows.Controls; namespace WpfTextOrPasswordBox { public class MultiLinePasswordBox : TextBox { private StringBuilder passwordBuilder = new StringBuilder(); private string previousText = string.Empty; private bool isUpdating = false; public char PasswordChar { get { return (char)GetValue(PasswordCharProperty); } set { SetValue(PasswordCharProperty, value); } } public static readonly DependencyProperty PasswordCharProperty = DependencyProperty.Register("PasswordChar", typeof(char), typeof(MultiLinePasswordBox), new PropertyMetadata('●')); public string PlainText { get { return (string)GetValue(PlainTextProperty); } set { SetValue(PlainTextProperty, value); } } public static readonly DependencyProperty PlainTextProperty = DependencyProperty.Register("PlainText", typeof(string), typeof(MultiLinePasswordBox), new PropertyMetadata(string.Empty)); public MultiLinePasswordBox() { AcceptsReturn = true; TextWrapping = TextWrapping.Wrap; VerticalScrollBarVisibility = ScrollBarVisibility.Auto; TextChanged += PasswordTextBox_TextChanged; } private void PasswordTextBox_TextChanged(object sender, TextChangedEventArgs e) { if (isUpdating) return; isUpdating = true; var caretIndex = CaretIndex; var input = Text; if (string.IsNullOrWhiteSpace(Text)) { passwordBuilder.Clear(); } else { var s = passwordBuilder.Length; int lengthDifference = input.Length - previousText.Length; if (lengthDifference > 0) { var newText = input.Substring(caretIndex - lengthDifference, lengthDifference); passwordBuilder.Insert(caretIndex - lengthDifference, newText); } else if (lengthDifference < 0) { passwordBuilder.Remove(caretIndex, Math.Abs(lengthDifference)); if (passwordBuilder[caretIndex - 1].ToString() != input) { var index = passwordBuilder.ToString().IndexOf(passwordBuilder[caretIndex - 1]); passwordBuilder.Replace(passwordBuilder[caretIndex - 1], input.Last()); } } var maskedText = CreateMaskedTextWithLineBreaks(passwordBuilder.ToString()); TextChanged -= PasswordTextBox_TextChanged; Text = maskedText; TextChanged += PasswordTextBox_TextChanged; } previousText = Text; CaretIndex = caretIndex; PlainText = passwordBuilder.ToString(); isUpdating = false; } private string CreateMaskedTextWithLineBreaks(string text) { var maskedText = new StringBuilder(); foreach (char c in text) { if (c == '\r' || c == '\n') maskedText.Append(c); else maskedText.Append(PasswordChar.ToString()); } return maskedText.ToString(); } } }
2)MultiLinePasswordBoxSample.xaml
代碼如下:
<wd:Window x:Class="WpfTextOrPasswordBox.MultiLinePasswordBoxSample" 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:local="clr-namespace:WpfTextOrPasswordBox" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers" Title="MultiLinePasswordBoxSample - WPF開發(fā)者" Width="800" Height="450" WindowStartupLocation="CenterScreen" mc:Ignorable="d"> <Grid> <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBlock Margin="0,20"> <Run Text="明文:" /> <Run Text="{Binding ElementName=myMultiLinePasswordBox, Path=PlainText}" /> </TextBlock> <local:MultiLinePasswordBox x:Name="myMultiLinePasswordBox" Width="200" Height="60" wd:ElementHelper.CornerRadius="3" wd:ElementHelper.Watermark="請輸入授權(quán)碼" /> </StackPanel> </Grid> </wd:Window>
效果圖
到此這篇關(guān)于WPF實現(xiàn)授權(quán)碼顯示密文并支持換行的文章就介紹到這了,更多相關(guān)WPF授權(quán)碼顯示密文內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c#數(shù)據(jù)庫與TXT導(dǎo)入導(dǎo)出的實例
最近剛學(xué)完ADO.NET,做了個數(shù)據(jù)導(dǎo)入導(dǎo)出的題目,是將txt中的數(shù)據(jù)導(dǎo)入數(shù)據(jù)庫,然后將數(shù)據(jù)庫中的數(shù)據(jù)導(dǎo)出到txt中,這里說的數(shù)據(jù)的格式是“tom|23”,tom指名字,23指年齡。廢話也不多說了,大家直接看代碼。2013-04-04C# 使用multipart form-data方式post數(shù)據(jù)到服務(wù)器
這篇文章主要介紹了C# 使用multipart form-data方式post數(shù)據(jù)到服務(wù)器,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08