0

I'm doing a login view. Problem is that the PasswordBox cant be binded to the view model so im mapping a property of the view to the viewmodel.

This is the View

public partial class LoginView : MetroDataWindow
{
    /// <summary>
    /// Initializes a new instance of the <see cref="LoginView"/> class.
    /// </summary>
    public LoginView()
        : this(null) { }

    /// <summary>
    /// Initializes a new instance of the <see cref="LoginView"/> class.
    /// </summary>
    /// <param name="viewModel">The view model to inject.</param>
    /// <remarks>
    /// This constructor can be used to use view-model injection.
    /// </remarks>
    public LoginView(LoginViewModel viewModel)
        : base(viewModel)
    {
        InitializeComponent();
    }

    [ViewToViewModel(MappingType = ViewToViewModelMappingType.ViewToViewModel)]
    public SecureString Contrasena
    {
        get { return (SecureString)GetValue(ContrasenaPropiedad); }
        set { SetValue(ContrasenaPropiedad, value); }
    }

    // Using a DependencyProperty as the backing store for MapCenter.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ContrasenaPropiedad = DependencyProperty.Register("Contrasena", typeof(SecureString),
        typeof(LoginView), new PropertyMetadata(null, (sender, e) => ((LoginView)sender).UpdateContrasena()));

    private void UpdateContrasena()
    {
        MessageBox.Show("VIEW: FirstName changed to " + ContrasenaPropiedad.ToString());
    }

    private void tbPassword_PasswordChanged(object sender, RoutedEventArgs e)
    {
        Contrasena = tbPassword.SecurePassword;

    }

    protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
    {
        base.OnPropertyChanged(e);

        if (e.Property == ContrasenaPropiedad)
        {
            int i = 0;
        }
    }
}

this is the viewmodel part with the property

public static readonly PropertyData ContrasenaPropiedad = RegisterProperty("Contrasena", typeof(SecureString), null, (sender, e) => ((LoginViewModel)sender).OnContrasenaChange());

    public void OnContrasenaChange()
    {
        _messageService.Show("VIEW MODEL: FirstName changed to " + Contrasena.ToString());
    }

    public SecureString  Contrasena
    {
        get
        {
            return GetValue<SecureString >(ContrasenaPropiedad);
        }
        set
        {
            SetValue(ContrasenaPropiedad, value);
        }
    }

the onChange function of the viewmodel never triggers.

I based this code on the example given in the last comment in this question

Catel ViewToViewModel attribute

But it does not work. Am I missing something or was the bug commented there never fixed?

Also since the view is the only one changing the property should i use the ViewToViewModelMappingType.ViewToViewModel type instead? does it change the implementation of the mapping in any way?

Community
  • 1
  • 1

1 Answers1

1

Passwords are a special kind of breed. But Catel has a solution for that problem, the UpdateBindingOnPasswordChanged behavior:

<PasswordBox>
   <i:Interaction.Behaviors>
         <catel:UpdateBindingOnPasswordChanged Password="{Binding Password, Mode=TwoWay}" />
   </i:Interaction.Behaviors>
</PasswordBox>

ps. are you aware of Catel.Fody? It makes your code more readable and easier to write.

Geert van Horrik
  • 5,689
  • 1
  • 18
  • 32
  • Does the behavior allow you to bind on a SecureString property? I had to change the type of the property to string. Why didn't the original code work? Thanks on the tip on Fody – Salvador Ruiz Guevara Jul 16 '15 at 15:50
  • 1
    SecureString is a special kind of breed. From the top of my head, it implements IDisposable which hardly anybody knows so most of the time it's useless. PR with support for SecureString is always appreciated ;-) – Geert van Horrik Jul 16 '15 at 19:28
  • So Securestring is the one messing with the mapping? I have gone with a manual map of the property but if i can come with something better I will be posting the solution. In the mean time for most cases the string bind with the behavior should be enough. Thanks again for the fast answer Geert. – Salvador Ruiz Guevara Jul 16 '15 at 22:35