- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我尝试使用自定义 Behavior
将 PasswordBox
的 SecurePassword
属性绑定(bind)到我的 ViewModel
。遗憾的是它不能正常工作。
基本上,我向 Behavior
添加了一个属性,其中包含我的 ViewModel
的目标属性。
知道为什么它不起作用吗?
PS:我目前正在回家的路上,没有带笔记本电脑,我将在大约 15 分钟内用我的代码更新问题。但是,如果有人能发布想法或其他内容,那就太好了。
编辑
正如我所 promise 的,这是一些代码:)
首先是行为
:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Interactivity;
using System.Security;
namespace Knerd.Behaviors {
public class PasswordChangedBehavior : Behavior<PasswordBox> {
protected override void OnAttached() {
AssociatedObject.PasswordChanged += AssociatedObject_PasswordChanged;
base.OnAttached();
}
private void AssociatedObject_PasswordChanged(object sender, RoutedEventArgs e) {
if (AssociatedObject.Password != null)
TargetPassword = AssociatedObject.SecurePassword;
}
protected override void OnDetaching() {
AssociatedObject.PasswordChanged -= AssociatedObject_PasswordChanged;
base.OnDetaching();
}
public SecureString TargetPassword {
get { return (SecureString)GetValue(TargetPasswordProperty); }
set { SetValue(TargetPasswordProperty, value); }
}
// Using a DependencyProperty as the backing store for TargetPassword. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TargetPasswordProperty = DependencyProperty.Register("TargetPassword", typeof(SecureString), typeof(PasswordChangedBehavior), new PropertyMetadata(default(SecureString)));
}
}
密码框
:
<PasswordBox Grid.Column="1" Grid.Row="1" Margin="5" Width="300" MinWidth="200">
<i:Interaction.Behaviors>
<behaviors:PasswordChangedBehavior TargetPassword="{Binding Password}" />
</i:Interaction.Behaviors>
</PasswordBox>
最后,我的 ViewModel
部分。
private SecureString password;
public SecureString Password {
get { return password; }
set {
if (password != value) {
password = value;
OnPropertyChanged("Password");
}
}
}
我希望任何人都可以提供帮助,atm 我使用代码隐藏版本,但我宁愿不这样做。
编辑 2
实际上不起作用的是,TargetPassword
属性不会更新我的 ViewModel
最佳答案
创建附加属性
public static class PasswordBoxAssistant
{
public static readonly DependencyProperty BoundPassword =
DependencyProperty.RegisterAttached("BoundPassword", typeof(string), typeof(PasswordBoxAssistant), new PropertyMetadata(string.Empty, OnBoundPasswordChanged));
public static readonly DependencyProperty BindPassword = DependencyProperty.RegisterAttached(
"BindPassword", typeof (bool), typeof (PasswordBoxAssistant), new PropertyMetadata(false, OnBindPasswordChanged));
private static readonly DependencyProperty UpdatingPassword =
DependencyProperty.RegisterAttached("UpdatingPassword", typeof(bool), typeof(PasswordBoxAssistant), new PropertyMetadata(false));
private static void OnBoundPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
PasswordBox box = d as PasswordBox;
// only handle this event when the property is attached to a PasswordBox
// and when the BindPassword attached property has been set to true
if (d == null || !GetBindPassword(d))
{
return;
}
// avoid recursive updating by ignoring the box's changed event
box.PasswordChanged -= HandlePasswordChanged;
string newPassword = (string)e.NewValue;
if (!GetUpdatingPassword(box))
{
box.Password = newPassword;
}
box.PasswordChanged += HandlePasswordChanged;
}
private static void OnBindPasswordChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
// when the BindPassword attached property is set on a PasswordBox,
// start listening to its PasswordChanged event
PasswordBox box = dp as PasswordBox;
if (box == null)
{
return;
}
bool wasBound = (bool)(e.OldValue);
bool needToBind = (bool)(e.NewValue);
if (wasBound)
{
box.PasswordChanged -= HandlePasswordChanged;
}
if (needToBind)
{
box.PasswordChanged += HandlePasswordChanged;
}
}
private static void HandlePasswordChanged(object sender, RoutedEventArgs e)
{
PasswordBox box = sender as PasswordBox;
// set a flag to indicate that we're updating the password
SetUpdatingPassword(box, true);
// push the new password into the BoundPassword property
SetBoundPassword(box, box.Password);
SetUpdatingPassword(box, false);
}
public static void SetBindPassword(DependencyObject dp, bool value)
{
dp.SetValue(BindPassword, value);
}
public static bool GetBindPassword(DependencyObject dp)
{
return (bool)dp.GetValue(BindPassword);
}
public static string GetBoundPassword(DependencyObject dp)
{
return (string)dp.GetValue(BoundPassword);
}
public static void SetBoundPassword(DependencyObject dp, string value)
{
dp.SetValue(BoundPassword, value);
}
private static bool GetUpdatingPassword(DependencyObject dp)
{
return (bool)dp.GetValue(UpdatingPassword);
}
private static void SetUpdatingPassword(DependencyObject dp, bool value)
{
dp.SetValue(UpdatingPassword, value);
}
}
并且在您的 XAML
<Page xmlns:ff="clr-namespace:FunctionalFun.UI">
<!-- [Snip] -->
<PasswordBox x:Name="PasswordBox"
ff:PasswordBoxAssistant.BindPassword="true" ff:PasswordBoxAssistant.BoundPassword="{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</Page>
你可能不想这样做,但如果你真的想继续的话。
The reason the WPF/Silverlight PasswordBox doesn't expose a DP for the Password property is security related. If WPF/Silverlight were to keep a DP for Password it would require the framework to keep the password itself unencrypted in memory. Which is considered quite a troublesome security attack vector. The PasswordBox uses encrypted memory (of sorts) and the only way to access the password is through the CLR property.
我建议在访问 PasswordBox.Password CLR 属性时,不要将它放在任何变量中或作为任何属性的值。将您的密码以明文形式保存在客户端计算机 RAM 中是安全禁忌。
SecurePassword
无法通过绑定(bind)完成。
.NET documentation explains why the PasswordBox was not made bindable in the first place.
另一种解决方案是将 PasswordBox
放入您的 ViewModel
public class LoginViewModel
public class LoginViewModel
{
// other properties here
public PasswordBox Password
{
get { return m_passwordBox; }
}
// Executed when the Login button is clicked.
private void LoginExecute()
{
var password = Password.SecurePassword;
// do more stuff...
}
}
是的,您在这里违反了 ViewModel 最佳实践,但是
关于c# - 将 SecurePassword 绑定(bind)到 ViewModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23020163/
我正在关注 Michale harlt 的 ruby on rails 教程。一切都很顺利,直到我陷入这个问题,在输入用户名和密码并单击“登录”按钮后,我收到了一个错误 ” ActiveModel
我尝试按照http://bcardarella.com/post/4668842452/exploring-rails-3-1-activemodel-securepassword使用rails 3.
我尝试使用自定义 Behavior 将 PasswordBox 的 SecurePassword 属性绑定(bind)到我的 ViewModel。遗憾的是它不能正常工作。 基本上,我向 Behavio
我是一名优秀的程序员,十分优秀!