[WPF] implement password binding in the password box
Zhou yinhui
Just like binding the text attribute of the Textbox Control, we hope to bind the Password attribute of the passwordbox space. For example, in mvvm mode, this seems necessary, but unfortunately, the Password attribute cannot be bound (it is not a dependency attribute or inotifypropertychanged ).
This may be due to security considerations. however, in order to bind the Password attribute between the password in the view-layer Password box and other background layers, we can take the following steps: synchronize the password in the password box with a buffer, and bind the buffer with the background. the synchronization between the Password box and the buffer zone can adopt events for notification, and create the buffer zone as the dependency attribute. Then the buffer zone supports binding and provides the correct password for the background.
The buffer can be a hash table or other dictionary structure, so that the password box and the password in the buffer can be matched one by one, or attachproperty (additional attribute ), in fact, the additional attribute mechanism is to operate a large dictionary cached.
Public Static Class Passwordboxbindinghelper
{
Public Static Bool Getispasswordbindingenabled (dependencyobject OBJ)
{
Return ( Bool ) Obj. getvalue (ispasswordbindingenabledproperty );
}
Public Static VoidSetispasswordbindingenabled (dependencyobject OBJ,BoolValue)
{
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 )
{< br> passwordbox. passwordchanged -= passwordboxpasswordchanged;
If ( bool ) E. newvalue)
{< br> passwordbox. passwordchanged += passwordboxpasswordchanged;
}< br>
}< BR >}
// when the passwordbox's password changed, update the buffer
static void passwordboxpasswordchanged ( Object sender, routedeventargs E)
{< br> var passwordbox = (passwordbox) sender;
If ( ! string. equals (getbindedpassword (passwordbox), passwordbox. password)
{< br> setbindedpassword (passwordbox, passwordbox. password);
}< BR >}
Public static string getbindedpassword (dependencyobject OBJ)
{< br> return ( string ) obj. getvalue (bindedpasswordproperty);
}
Public Static VoidSetbindedpassword (dependencyobject OBJ,StringValue)
{
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 the following: < Passwordbox Helpers: passwordboxbindinghelper. ispasswordbindingenabled = "True"
Helpers: passwordboxbindinghelper. bindedpassword =
" {Binding Path = password, mode = twoway, updatesourcetrigger = propertychanged} " />
In addition, after changing the password, you need to manually update the location of the caretindex in the password box. Unfortunately, the password box does not provide us with such attributes or methods (textbox has, passwordbox does not). You can set them using the following methods: Private Static Void Setpasswordboxselection (passwordbox, Int Start, Int Length)
{
VaR select = Passwordbox. GetType (). getmethod ( " Select " ,
Bindingflags. Instance | Bindingflags. nonpublic );
Select. Invoke (passwordbox,New Object[] {Start, length });
}