我遇到了绑定到密码盒的问题。这似乎是一个安全风险,但我正在使用MVVM模式,所以我希望绕过这个。我在这里发现了一些有趣的代码(有人使用过这个或类似的代码吗?)
http://www.wpftutorial.net/PasswordBox.html
从技术上讲,它看起来很棒,但我不确定如何检索密码。
我基本上有属性在我的LoginViewModel用户名和密码。用户名是好的,正在工作,因为它是一个文本框。
我使用上面的代码,并输入这个
<PasswordBox ff:PasswordHelper.Attach="True"
ff:PasswordHelper.Password="{Binding Path=Password}" Width="130"/>
当我有PasswordBox作为一个文本框和绑定路径=密码,然后在我的LoginViewModel属性更新。
我的代码非常简单,基本上我有一个命令为我的按钮。当我按下它CanLogin被调用,如果它返回真,它调用Login。
你可以看到,我检查了我的用户名属性,这很好。
在登录我发送到我的服务的用户名和密码,用户名包含数据从我的视图,但密码是空|空
private DelegateCommand loginCommand;
public string Username { get; set; }
public string Password { get; set; }
public ICommand LoginCommand
{
get
{
if (loginCommand == null)
{
loginCommand = new DelegateCommand(
Login, CanLogin );
}
return loginCommand;
}
}
private bool CanLogin()
{
return !string.IsNullOrEmpty(Username);
}
private void Login()
{
bool result = securityService.IsValidLogin(Username, Password);
if (result) { }
else { }
}
这就是我正在做的
<TextBox Text="{Binding Path=Username, UpdateSourceTrigger=PropertyChanged}"
MinWidth="180" />
<PasswordBox ff:PasswordHelper.Attach="True"
ff:PasswordHelper.Password="{Binding Path=Password}" Width="130"/>
我有我的文本框,这是没有问题的,但在我的ViewModel密码是空的。
是我做错了什么还是漏了一步?
我放了一个断点,果然代码进入静态助手类,但它从不更新我的ViewModel中的密码。
为了在不破坏MVVM的情况下解决OP问题,我将使用自定义值转换器和必须从密码框中检索的值(密码)的包装器。
public interface IWrappedParameter<T>
{
T Value { get; }
}
public class PasswordBoxWrapper : IWrappedParameter<string>
{
private readonly PasswordBox _source;
public string Value
{
get { return _source != null ? _source.Password : string.Empty; }
}
public PasswordBoxWrapper(PasswordBox source)
{
_source = source;
}
}
public class PasswordBoxConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// Implement type and value check here...
return new PasswordBoxWrapper((PasswordBox)value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new InvalidOperationException("No conversion.");
}
}
在视图模型中:
public string Username { get; set; }
public ICommand LoginCommand
{
get
{
return new RelayCommand<IWrappedParameter<string>>(password => { Login(Username, password); });
}
}
private void Login(string username, string password)
{
// Perform login here...
}
因为视图模型使用IWrappedParameter<T>,所以它不需要任何关于PasswordBoxWrapper或PasswordBoxConverter的知识。这样您就可以将PasswordBox对象与视图模型隔离开来,并且不会破坏MVVM模式。
在视图中:
<Window.Resources>
<h:PasswordBoxConverter x:Key="PwdConverter" />
</Window.Resources>
...
<PasswordBox Name="PwdBox" />
<Button Content="Login" Command="{Binding LoginCommand}"
CommandParameter="{Binding ElementName=PwdBox, Converter={StaticResource PwdConverter}}" />
为了在不破坏MVVM的情况下解决OP问题,我将使用自定义值转换器和必须从密码框中检索的值(密码)的包装器。
public interface IWrappedParameter<T>
{
T Value { get; }
}
public class PasswordBoxWrapper : IWrappedParameter<string>
{
private readonly PasswordBox _source;
public string Value
{
get { return _source != null ? _source.Password : string.Empty; }
}
public PasswordBoxWrapper(PasswordBox source)
{
_source = source;
}
}
public class PasswordBoxConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// Implement type and value check here...
return new PasswordBoxWrapper((PasswordBox)value);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new InvalidOperationException("No conversion.");
}
}
在视图模型中:
public string Username { get; set; }
public ICommand LoginCommand
{
get
{
return new RelayCommand<IWrappedParameter<string>>(password => { Login(Username, password); });
}
}
private void Login(string username, string password)
{
// Perform login here...
}
因为视图模型使用IWrappedParameter<T>,所以它不需要任何关于PasswordBoxWrapper或PasswordBoxConverter的知识。这样您就可以将PasswordBox对象与视图模型隔离开来,并且不会破坏MVVM模式。
在视图中:
<Window.Resources>
<h:PasswordBoxConverter x:Key="PwdConverter" />
</Window.Resources>
...
<PasswordBox Name="PwdBox" />
<Button Content="Login" Command="{Binding LoginCommand}"
CommandParameter="{Binding ElementName=PwdBox, Converter={StaticResource PwdConverter}}" />