使用 MVVM 时,如何使 TextBox 成为“密码框”并显示星星?
Posted
技术标签:
【中文标题】使用 MVVM 时,如何使 TextBox 成为“密码框”并显示星星?【英文标题】:How can I make a TextBox be a "password box" and display stars when using MVVM? 【发布时间】:2010-11-10 07:33:13 【问题描述】:如何在 XAML 中执行此操作:
伪代码:
<TextBox Text="Binding Password" Type="Password"/>
以便用户在输入密码时看到星号或圆点。
我试过 various examples 建议 PasswordChar 和 PasswordBox 但无法让这些工作。
例如我可以这样做,如图here:
<PasswordBox Grid.Column="1" Grid.Row="1"
PasswordChar="*"/>
但我当然想将 Text 属性绑定到我的 ViewModel,以便在单击按钮时将值发送到绑定的 TextBox(不使用后面的代码),我想这样做:
<TextBox Grid.Column="1" Grid.Row="0"
Text="Binding Login"
Style="StaticResource FormTextBox"/>
<PasswordBox Grid.Column="1" Grid.Row="1"
Text="Binding Password"
PasswordChar="*"
Style="StaticResource FormTextBox"/>
但是 PasswordBox 没有 Text 属性。
【问题讨论】:
您能否详细说明为什么 PasswordChar 和 PasswordBox 不起作用? 使用MVVM似乎不是那么直接,我在这里发现了一个类似的问题:***.com/questions/1097235/passwordbox-with-mvvm 【参考方案1】:要获取或设置 PasswordBox 中的密码,请使用 Password 属性。比如
string password = PasswordBox.Password;
据我所知,这不支持数据绑定,所以你必须在代码隐藏中设置值,并相应地更新它。
【讨论】:
可以提一下:正如 Tasnim Fabiha 所提到的,可以更改 TextBox 的字体以便仅显示点/星号。但是我找不到他的字体……所以我给你我的工作示例:
<TextBox Text="Binding Password"
FontFamily="pack://application:,,,/Resources/#password" />
只是复制粘贴是行不通的。首先你必须下载提到的字体“password.ttf” 链接:https://github.com/davidagraf/passwd/blob/master/public/ttf/password.ttf 然后将其复制到您的项目资源文件夹(项目->属性->资源->添加资源->添加现有文件)。然后将其 Build Action 设置为:Resource。
之后你只会看到点,但你仍然可以从中复制文本,因此需要禁用 CTRL+C 快捷键,如下所示:
<TextBox Text="Binding Password"
FontFamily="pack://application:,,,/Resources/#password" >
<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>
编辑: 添加了基于@CodingNinja评论的Ctrl+X和上下文菜单禁用,谢谢。
【讨论】:
这个字体不适合我。文本保持完全相同,而不是密码字符...如果您有任何提示,我将不胜感激。谢谢 对我来说它有效(也在 .NET 4.8 上测试过)。尝试使用 FontFamily 位置,我认为它可能会略有不同,并确保您将其作为 RESOURCE。 谢谢!非常适合我。能够显示点并禁用 CTRL-C。真的很感激! 不客气。为了使其 100% 安全,还禁用 CTRL+X (CUT) 快捷方式。 @ssamko 不要忘记在上下文菜单中复制/粘贴! ***.com/a/3484929/4380178【参考方案3】:将密码框控件作为参数发送到您的登录命令。
<Button Command="Binding LoginCommand" CommandParameter="Binding ElementName=PasswordBox"...>
然后你可以在你的视图模型中调用CType(parameter, PasswordBox).Password
。
【讨论】:
这违反了 MVVM 模式。【参考方案4】:这里有一种绑定 PasswordBox 的方法:PasswordBox Databinding
【讨论】:
【参考方案5】:谢谢科迪,这很有帮助。我刚刚为使用 C# 中的委托命令的人添加了一个示例
<PasswordBox x:Name="PasswordBox"
Grid.Row="1" Grid.Column="1"
HorizontalAlignment="Left"
Width="300" Height="25"
Margin="6,7,0,7" />
<Button Content="Login"
Grid.Row="4" Grid.Column="1"
Style="StaticResource StandardButton"
Command="Binding LoginCommand"
CommandParameter="Binding ElementName=PasswordBox"
Height="31" Width="92"
Margin="5,9,0,0" />
public ICommand LoginCommand
get
return new DelegateCommand<object>((args) =>
// Get Password as Binding not supported for control-type PasswordBox
LoginPassword = ((PasswordBox) args).Password;
// Rest of code here
);
【讨论】:
【参考方案6】:您只需将以下值添加到您的TextBox
控件的FontFamily
属性中,即可将您的TextBox
设为自定义PasswordBox
。
<TextBox
Text="Binding Password"
FontFamily="ms-appx:///Assets/PassDot.ttf#PassDot"
FontSize="35"/>
就我而言,这非常有效。这将显示点代替实际文本(不是星号(*))。
【讨论】:
这家伙是个英雄!一个奇怪的人,但仍然是一个英雄! 我希望这会起作用,但对我来说它仍然显示文本。我必须下载 PassDot.ttf 吗? @rabejens 是的,你必须下载它。 您可以捆绑字体并将其作为资源加载。 @TasnimFabiha 下载链接?【参考方案7】:使用 PasswordBox 的问题在于它对 MVVM 不是很友好,因为它可以与 SecureString 一起使用,因此需要一个 shim 将其绑定到字符串。您也不能使用剪贴板。虽然所有这些东西都是有原因的,但您可能不需要那种级别的安全性。这是一种适用于剪贴板的替代方法,没什么特别的。您使 TextBox 文本和背景透明,并将文本绑定到其下方的 TextBlock。此文本块使用指定的转换器将字符转换为 *。
<Window.Resources>
<local:TextToPasswordCharConverter x:Key="TextToPasswordCharConverter" />
</Window.Resources>
<Grid Width="200">
<TextBlock Margin="5,0,0,0" Text="Binding Text, Converter=StaticResource TextToPasswordCharConverter, UpdateSourceTrigger=PropertyChanged, Mode=OneWay" FontFamily="Consolas" VerticalAlignment="Center" />
<TextBox Foreground="Transparent" Text="Binding Text, UpdateSourceTrigger=PropertyChanged" FontFamily="Consolas" Background="Transparent" />
</Grid>
这里是值转换器:
class TextToPasswordCharConverter : IValueConverter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
return new String('*', value?.ToString().Length ?? 0);
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
throw new NotImplementedException();
确保视图模型上的 Text 属性实现 INotifyPropertyChanged
【讨论】:
【参考方案8】:我从 Views 代码隐藏中执行了以下操作,以在视图模型中设置我的属性。不确定它是否真的“打破”了 MVVM 模式,但它是找到的最佳且最简单的解决方案。
var data = this.DataContext as DBSelectionViewModel;
data.PassKey = txtPassKey.Password;
【讨论】:
【参考方案9】:对我有用的一个简单解决方案是将文本框绑定到显示重复 * 的转换值的 LocalPassword。任何条目都存储在 _localPassword 变量中。
<TextBox Text="Binding LocalPassword" />
private string _localPassword = null;
private string _localPasswordDisplayed get => new string('*', _localPassword.Length);
public string LocalPassword get => _localPasswordDisplayed; set _localPassword = value; OnPropertyChanged();
【讨论】:
以上是关于使用 MVVM 时,如何使 TextBox 成为“密码框”并显示星星?的主要内容,如果未能解决你的问题,请参考以下文章
如何连接 TextBox 的 TextChanged 事件和命令以便在 Silverlight 中使用 MVVM 模式
MVVM 和 TextBox 的 SelectedText 属性
Mvvm KeyDown的实现以及TextBox绑定的属性不更新问题的解决
WPF MVVM - 如何绑定自定义控件->ToggleButton.IsChecked 到 View->TextBox.Text