我遇到了绑定到密码盒的问题。这似乎是一个安全风险,但我正在使用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中的密码。


当前回答

<UserControl x:Class="Elections.Server.Handler.Views.LoginView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:cal="http://www.caliburnproject.org" mc:Ignorable="d" Height="531" Width="1096"> <ContentControl> <ContentControl.Background> <ImageBrush/> </ContentControl.Background> <Grid > <Border BorderBrush="#FFABADB3" BorderThickness="1" HorizontalAlignment="Left" Height="23" Margin="900,100,0,0" VerticalAlignment="Top" Width="160"> <TextBox TextWrapping="Wrap"/> </Border> <Border BorderBrush="#FFABADB3" BorderThickness="1" HorizontalAlignment="Left" Height="23" Margin="900,150,0,0" VerticalAlignment="Top" Width="160"> <PasswordBox x:Name="PasswordBox"/> </Border> <Button Content="Login" HorizontalAlignment="Left" Margin="985,200,0,0" VerticalAlignment="Top" Width="75"> <i:Interaction.Triggers> <i:EventTrigger EventName="Click"> <cal:ActionMessage MethodName="Login"> <cal:Parameter Value="{Binding ElementName=PasswordBox}" /> </cal:ActionMessage> </i:EventTrigger> </i:Interaction.Triggers> </Button> </Grid> </ContentControl> </UserControl>

using System; using System.Windows; using System.Windows.Controls; using Caliburn.Micro; namespace Elections.Server.Handler.ViewModels { public class LoginViewModel : PropertyChangedBase { MainViewModel _mainViewModel; public void SetMain(MainViewModel mainViewModel) { _mainViewModel = mainViewModel; } public void Login(Object password) { var pass = (PasswordBox) password; MessageBox.Show(pass.Password); //_mainViewModel.ScreenView = _mainViewModel.ControlPanelView; //_mainViewModel.TitleWindow = "Panel de Control"; //HandlerBootstrapper.Title(_mainViewModel.TitleWindow); } } }

,简单!

其他回答

你可以使用这个XAML:

<PasswordBox>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="PasswordChanged">
            <i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=PasswordBox}}" CommandParameter="{Binding ElementName=PasswordBox}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</PasswordBox>

该命令的执行方法:

private void ExecutePasswordChangedCommand(PasswordBox obj)
{ 
   if (obj != null)
     Password = obj.Password;
}

这需要将System.Windows.Interactivity程序集添加到项目中,并通过xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"引用它。

正如你所看到的,我绑定到密码,但也许它绑定到静态类..

它是一个附加属性。这种属性可以应用于任何类型的DependencyObject,而不仅仅是声明它的类型。因此,尽管它是在PasswordHelper静态类中声明的,但它还是应用于使用它的PasswordBox。

要使用这个附加属性,你只需要将它绑定到ViewModel中的Password属性:

<PasswordBox w:PasswordHelper.Attach="True" 
         w:PasswordHelper.Password="{Binding Password}"/>

我使用这种方法并通过密码框,虽然这确实违反了MVVM,这对我来说是必不可少的,因为我正在使用一个内容控件与数据模板为我的登录在我的shell,这是一个复杂的shell环境。因此,访问shell背后的代码将是垃圾。

据我所知,我认为传递密码框与从后面的代码访问控制权是一样的。在这个实现中,我没有视图模型中的密码属性。

按钮命令

Command="{Binding Path=DataContext.LoginCommand, ElementName=MyShell}" CommandParameter="{Binding ElementName=PasswordBox}"

ViewModel

private void Login(object parameter)
{
    System.Windows.Controls.PasswordBox p = (System.Windows.Controls.PasswordBox)parameter;
    MessageBox.Show(p.Password);
}

如果你想把它组合在一个控件和一个命令中

<PasswordBox Name="PasswordBoxPin" PasswordChar="*">
    <PasswordBox.InputBindings>
        <KeyBinding Key="Return" Command="{Binding AuthentifyEmpCommand}" CommandParameter="{Binding ElementName=PasswordBoxPin}"/>
    </PasswordBox.InputBindings>
</PasswordBox>

在你的Vm上(就像Konamiman展示的那样)

public void AuthentifyEmp(object obj)
{
    var passwordBox = obj as PasswordBox;
    var password = passwordBox.Password;
}
private RelayCommand _authentifyEmpCommand;
public RelayCommand AuthentifyEmpCommand => _authentifyEmpCommand ?? (_authentifyEmpCommand = new RelayCommand(AuthentifyEmp, null));

编辑:根据评论,我觉得有必要指出这违反了MVVM模式,只有当这不是您主要关注的问题之一时才使用它。

我做过这样的事情:

XAML:

<PasswordBox x:Name="NewPassword" PasswordChanged="NewPassword_PasswordChanged"/>
<!--change tablenameViewSource: yours!-->
<Grid DataContext="{StaticResource tablenameViewSource}" Visibility="Hidden">
        <TextBox x:Name="Password" Text="{Binding password, Mode=TwoWay}"/>
</Grid>

C#:

private void NewPassword_PasswordChanged(object sender, RoutedEventArgs e)
    {
        try
        {
           //change tablenameDataTable: yours! and tablenameViewSource: yours!
           tablenameDataTable.Rows[tablenameViewSource.View.CurrentPosition]["password"] = NewPassword.Password;
        }
        catch
        {
            this.Password.Text = this.NewPassword.Password;
        }
    }

这对我很管用!