Just as the Text property of the TextBox control is bound, we want to be able to bind the password property of the PasswordBox space, such as in the MVVM pattern, which seems to be necessary, but unfortunately, the password property is not a binding (not a dependency property, Also did not implement INotifyPropertyChanged).
This may be due to security considerations. But in order to implement the binding between the password in the View Layer password box and the other layers in the background, the following ideas can be taken: the password of the password box is synchronized with one buffer, and the buffer is bound to the background. The synchronization between the password box and the buffer can be notified by the event, and the buffer is created as a dependency property, then the buffer supports binding, and provides the correct password to the background.
The buffer can be a hash table or other dictionary structure, in order to match the password box and the buffer in the password one by one, you can also make attachproperty (attached property), in fact, the mechanism of the attached property is the cache of a large dictionary operation
public static Class Passwordboxbindinghelper
{
public static bool Getispasswordbindingenabled (DependencyObject obj)
{
return (bool) obj. GetValue (Ispasswordbindingenabledproperty);
}
public static void setispasswordbindingenabled (DependencyObject obj, bool value)
{
Obj. SetValue (ispasswordbindingenabledproperty, value);
}
public static readonly DependencyProperty Ispasswordbindingenabledproperty =
Dependencyproperty.registerattached ("ispasswordbindingenabled", typeof (BOOL),
typeof (Passwordboxbindinghelper),
New UIPropertyMetadata (False, onispasswordbindingenabledchanged));
private static void Onispasswordbindingenabledchanged (DependencyObject obj,
DependencyPropertyChangedEventArgs e)
{
var passwordBox = obj as PasswordBox;
if (PasswordBox! = null)
{
Passwordbox.passwordchanged-= passwordboxpasswordchanged;
if ((bool) e.newvalue)
{
Passwordbox.passwordchanged + = passwordboxpasswordchanged;
}
}
}
When the PasswordBox ' s password changed, update the buffer
static void Passwordboxpasswordchanged (object sender, RoutedEventArgs e)
{
var PasswordBox = (passwordBox) sender;
if (! String.Equals (Getbindedpassword (PasswordBox), Passwordbox.password))
{
Setbindedpassword (PasswordBox, Passwordbox.password);
}
}
public static string Getbindedpassword (DependencyObject obj)
{
return (string) obj. GetValue (Bindedpasswordproperty);
}
public static void Setbindedpassword (DependencyObject obj, string value)
{
Obj. SetValue (bindedpasswordproperty, value);
}
public static readonly DependencyProperty Bindedpasswordproperty =
Dependencyproperty.registerattached ("Bindedpassword", typeof (String),
typeof (Passwordboxbindinghelper),
New UIPropertyMetadata (String. Empty, onbindedpasswordchanged));
When the buffer changed, upate the PasswordBox ' s password
private static void Onbindedpasswordchanged (DependencyObject obj,
DependencyPropertyChangedEventArgs e)
{
var passwordBox = obj as PasswordBox;
if (PasswordBox! = null)
{
Passwordbox.password = E.newvalue = = null? String. Empty:e.newvalue.tostring ();
}
}
In the view layer, you can use it as follows:<passwordbox helpers:passwordboxbindinghelper.ispasswordbindingenabled= "True"
helpers:passwordboxbindinghelper.bindedpassword=
"{Binding Path=password, Mode=twoway, updatesourcetrigger=propertychanged}"/>In addition, after changing the password box password, you need to manually update the location of the Password box caret (caretindex), unfortunately, the password box does not provide us with such a property or method (TextBox has, PasswordBox not), you can use the following method to set: private static void Setpasswordboxselection (PasswordBox PasswordBox, int start, int length)
{
var select = Passwordbox.gettype (). GetMethod ("select",
BindingFlags.Instance | BindingFlags.NonPublic);
Select. Invoke (PasswordBox, new object[] {start, length});
}Add in view:
<PasswordBox x:Name=
"pbPassword"
Grid.Row=
"1"
Grid.Column=
"2"
MaxWidth=
"300"
Width=
"300"
HorizontalAlignment=
"Center"
VerticalAlignment=
"Center"
local:PasswordBoxBindingHelper.IsPasswordBindingEnabled=
"True"
local:PasswordBoxBindingHelper.BindedPassword=
"{Binding Path=Password, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
PasswordChanged=
"pbPassword_PasswordChanged"
/>
Then in the view's CS (in the Background code) add:
private
void
pbPassword_PasswordChanged(
object
sender, RoutedEventArgs e)
{
PasswordBox passwordtext = (PasswordBox)sender;
SetPasswordBoxSelection(passwordtext, passwordtext.Password.Length + 1, passwordtext.Password.Length + 1);
}
private
static
void
SetPasswordBoxSelection(PasswordBox passwordBox,
int
start,
int
length)
{
var
select
= passwordBox.GetType().GetMethod(
"Select"
,
BindingFlags.Instance | BindingFlags.NonPublic);
select
.Invoke(passwordBox,
new
object
[] { start, length });
}
[WPF] Implementing password bindings for password boxes