How to validate PasswordBox WPF
Solution 1
Try setting ValidatesOnDataErrors=True
and ValidatesOnExceptions=True
on your binding:
<PasswordBox ...
local:PasswordBoxAssistant.BoundPassword="{Binding Path=Password,
UpdateSourceTrigger=Explicit,
ValidatesOnDataErrors=True,
ValidatesOnExceptions=True}"
/>
Solution 2
Set Mode=TwoWay on your binding
local:PasswordBoxAssistant.BoundPassword="{Binding Path=Password,Mode=TwoWay,
UpdateSourceTrigger=Explicit}"
Solution 3
Another solution, without using any "unsecure" string in the middle, is to adapt the Window code, something like this:
Let's suppose I have an MVVM object like this, with WPF validation using IDataErrorInfo:
public class MyObject : INotifyPropertyChanged, IDataErrorInfo
{
...
public SecureString SecurePassword
{
get
{ ... }
set
{
...
OnPropertyChanged("SecurePassword");
}
}
...
string IDataErrorInfo.Error { get { return Validate(null); } }
string IDataErrorInfo.this[string columnName] { get { return Validate(columnName); } }
private string Validate(string memberName)
{
string error = null;
...
if (memberName == "SecurePassword" || memberName == null)
{
// this is where I code my custom business rule
if (SecurePassword == null || SecurePassword.Length == 0)
{
error = "Password must be specified.";
}
}
...
return error;
}
}
And a Window Xaml with a PasswordBox like this:
<PasswordBox Name="MyPassword" PasswordChanged="MyPassword_Changed" ... />
Then, the corresponding Window code like this will trigger PasswordBox binding:
// add a custom DependencyProperty
public static readonly DependencyProperty SecurePasswordProperty =
DependencyProperty.RegisterAttached("SecurePassword", typeof(SecureString), typeof(MyWindow));
public MyWindow()
{
InitializeComponent();
DataContext = myObject; // created somewhere
// create a binding by code
Binding passwordBinding = new Binding(SecurePasswordProperty.Name);
passwordBinding.Source = myObject;
passwordBinding.ValidatesOnDataErrors = true;
// you can configure other binding stuff here
MyPassword.SetBinding(SecurePasswordProperty, passwordBinding);
}
private void MyPassword_Changed(object sender, RoutedEventArgs e)
{
// this should trigger binding and therefore validation
((MyObject)DataContext).SecurePassword = MyPassword.SecurePassword;
}
Solution 4
As far as I remember, the only way to add validation on a PasswordBox is to throw a new ValidationException in the setter of the binding property for SecurePassword. The PasswordBoxAssistant will not help you with this.
Related videos on Youtube
Sonhja
Partially programmer, partially designer! An WPF lover, Android developer and .Net contributor! Learning more and more everyday :) And happy to help others work!
Updated on September 15, 2022Comments
-
Sonhja over 1 year
I'm trying to make a validation for a
PasswordBox
. For making validations I followed this link, that shows how to validate onTextBox
.The problem comes with
PasswordBoxes
. Because itsPassword
is not bindable due to security reasons, I tried to make a binding following this link (also explained here, for CodeProject users).So, apparently, fantastic! I can bind my
PasswordBox
with itsPassword
property, so then I can bind with my validation. But it ignores me...This is a regular
TextBox
that I use and works fine:<local:ErrorProvider Grid.Column="1" Grid.Row="2" > <TextBox Width="160" HorizontalAlignment="Left" Name="textBoxUserPass" Text="{Binding Path=Password, UpdateSourceTrigger=Explicit}" /> </local:ErrorProvider>
And this is the
PasswordBox
I tried to simulate:<local:ErrorProvider Grid.Column="1" Grid.Row="2" > <PasswordBox Width="160" HorizontalAlignment="Left" Name="textBoxUserPass" local:PasswordBoxAssistant.BindPassword="True" local:PasswordBoxAssistant.BoundPassword="{Binding Path=Password, UpdateSourceTrigger=Explicit}" /> </local:ErrorProvider>
This is how I get the
BindingExpression
for eachTextBox
:BindingExpression beUserName = textBoxUserName.GetBindingExpression(TextBox.TextProperty); if (beUserName != null) beUserName.UpdateSource();
And this is how I get it for the
PasswordBox
:BindingExpression bePassword = textBoxUserPass.GetBindingExpression(PasswordBoxAssistant.BoundPassword); if (bePassword != null) bePassword.UpdateSource();
If we made any mistake (defined on my Validation class), when I do this:
if (!beUserName.HasError && !bePassword.HasError)
each
BindingExpression
should say true of false depending on error validations. But for myPasswordBox
never gets the value... Any idea?-
James over 9 yearswhere is this PasswordBoxAssistant that everyone seems to be using?
-
Charlie over 9 yearsPasswordBoxAssistant: blog.functionalfun.net/2008/06/…
-
-
Sonhja about 11 yearsHummm can you provide an example or link? It sounds as a solution.
-
Cristian Chereches about 11 yearsThis is what I found in an old app that I was working on:public SecureString NewPassword { get { return _newPassword; } set { _newPassword = value; string error = IsPasswordValid(); if (!string.IsNullOrEmpty(error)) { throw new ValidationException(error); } } }
-
Sonhja about 11 yearsHummm, gonna try it, but the exact solution is the one Richard Deeming posted (for this case). But I'm gonna try this one too, as I have this particular case also at my code.
-
Daniel over 5 yearsI do hope people realize the PasswordBox is itself insecure, since it will happily decrypt the password for any application that asks nicely. Just attach to the process, and via reflection, say, "Hey PasswordBox, what's in the Password property?" I get that you can get a little protection from memory scraping, specifically, by avoiding storing it in a string field, but for most use cases, it's already game over if any malicious payload has been installed--and perhaps not really worth fretting over.
-
Simon Mourier over 5 years@Daniel - SecureString's does not protect from a live debugger or similar live threats. A good explanation of handled threats is here: blogs.msdn.microsoft.com/shawnfa/2004/05/27/… (also make sure you read comments from Shawn)