20

Hi people stackoverflow. I'm working with MVVM, I have ViewModel call UserViewModel with a Property Password. In the View have a control PasswordBox.

<PasswordBox x:Name="txtPassword" Password="{Binding Password}" />

But this xaml don't work. How do you do the binding?? Help please!!

4

5 回答 5

13

出于安全原因,Password 属性不是依赖属性,因此您不能绑定到它。不幸的是,您需要在老式方式后面的代码中执行绑定(注册 OnPropertyChanged 事件并通过代码更新值......)


我快速搜索将我带到这篇博客文章,该文章展示了如何编写附加属性来回避这个问题。这是否值得做虽然真的取决于你对代码隐藏的厌恶。

于 2009-07-08T10:24:53.103 回答
4

您始终可以编写一个包含 Password 并为 Password 属性添加依赖项属性的控件。

我只会使用后面的代码,但如果你必须这样做,你可以这样做:

public class BindablePasswordBox : Decorator
{
    public static readonly DependencyProperty PasswordProperty =
        DependencyProperty.Register("Password", typeof(string), typeof(BindablePasswordBox));

    public string Password
    {
        get { return (string)GetValue(PasswordProperty); }
        set { SetValue(PasswordProperty, value); }
    }

    public BindablePasswordBox()
    {
        Child = new PasswordBox();
        ((PasswordBox)Child).PasswordChanged += BindablePasswordBox_PasswordChanged;
    }

    void BindablePasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
    {
        Password = ((PasswordBox)Child).Password;
    }

}
于 2009-07-08T10:50:17.920 回答
4

BindablePasswordBox 存在问题。它只在一个方向上起作用,从 PasswordBox 到 PasswordProperty。下面是它的修改版本,可以双向工作。它注册一个 PropertyChangedCallback 并在调用时更新 PasswordBox 的密码。我希望有人觉得这很有用。

public class BindablePasswordBox : Decorator
{
    public static readonly DependencyProperty PasswordProperty = DependencyProperty.Register("Password", typeof(string), typeof(BindablePasswordBox), new PropertyMetadata(string.Empty, OnDependencyPropertyChanged));
    public string Password
    {
        get { return (string)GetValue(PasswordProperty); }
        set { SetValue(PasswordProperty, value); }
    }

    private static void OnDependencyPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
    {
        BindablePasswordBox p = source as BindablePasswordBox;
        if (p != null)
        {
            if (e.Property == PasswordProperty)
            {
                var pb = p.Child as PasswordBox;
                if (pb != null)
                {
                    if (pb.Password != p.Password)
                        pb.Password = p.Password;
                }
            }
        }
    }

    public BindablePasswordBox()
    {
        Child = new PasswordBox();
        ((PasswordBox)Child).PasswordChanged += BindablePasswordBox_PasswordChanged;
    }

    void BindablePasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
    {
        Password = ((PasswordBox)Child).Password;
    }
}
于 2014-01-24T14:35:53.690 回答
1

为了避免密码在内存中作为纯文本在任何时候都可用,我将值作为参数提供给我的命令。

<Label>User Name</Label>
<TextBox Text="{Binding UserName}" />
<Label>Password</Label>
<PasswordBox Name="PasswordBox" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0 16 0 0">
    <Button Margin="0 0 8 0" MinWidth="65" 
            Command="{Binding LoginAccept}" 
            CommandParameter="{Binding ElementName=PasswordBox}">
        Login
    </Button>
    <Button MinWidth="65" Command="{Binding LoginCancel}">Cancel</Button>
</StackPanel>

然后在我的视图模型中。

public DelegateCommand<object> LoginAccept { get; private set; }
public DelegateCommand<object> LoginCancel { get; private set; }

public LoginViewModel {
    LoginAccept = new DelegateCommand<object>(o => OnLogin(o), (o) => IsLoginVisible);
    LoginCancel = new DelegateCommand<object>(o => OnLoginCancel(), (o) => IsLoginVisible);
}

private void OnLogin(object o)
{
    var passwordBox = (o as System.Windows.Controls.PasswordBox);
    var password = passwordBox.SecurePassword.Copy();
    passwordBox.Clear();
    ShowLogin = false;
    var credential = new System.Net.NetworkCredential(UserName, password);
}

private void OnLoginCancel()
{
    ShowLogin = false;
}

虽然直接从绑定中提供 SecurePassword 是有意义的,但它似乎总是提供一个空值。所以这不起作用:

    <Button Margin="0 0 8 0" MinWidth="65" 
            Command="{Binding LoginAccept}" 
            CommandParameter="{Binding ElementName=PasswordBox, Path=SecurePassword}">
于 2016-03-07T16:12:17.137 回答
0

检查密码框上的另一个线程。最好不要将密码保存在任何 DP 或公共财产上。

密码箱上的其他线程

于 2013-08-13T06:07:56.260 回答