wpfui
wpfui copied to clipboard
ui:PasswordBox Binding issues
Describe the bug
Here are two bugs if I binding Text
as password(mvvm two-way)
- The password&text change double when
IsPasswordRevealed
is false - The
text
value is*
whenIsPasswordRevealed
is false, if I post thetext
to db the value saved in db is*
To Reproduce
Just binding a property
<ui:PasswordBox
Grid.Column="1"
MaxLength="64"
PasswordChar="*"
Text="{Binding ViewModel.Config.Passcode}" />
Expected behavior
Actually I just wanna find a property to bing two-way
Screenshots
Desktop:
- OS: [Windows11 21H2 22000.856]
- .NET: [net6.0]
- Version: [2.0.2]
Additional context
More info refer #373
Bugs may fire here
@pomianowski Please help to check and advise, thanks
@JeremyWu917 binding doesn't work for me, but the TextChanged
event does.
<ui:PasswordBox
Margin="0,8,0,0"
Icon="Password24"
MaxLength="64"
PasswordChar="*" TextChanged="PasswordBox_TextChanged"
PlaceholderText="Password" />
private void PasswordBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
{
if (e.Source is PasswordBox box)
{
string password = box.Password;
}
}
@JeremyWu917 binding doesn't work for me, but the
TextChanged
event does.<ui:PasswordBox Margin="0,8,0,0" Icon="Password24" MaxLength="64" PasswordChar="*" TextChanged="PasswordBox_TextChanged" PlaceholderText="Password" />
private void PasswordBox_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e) { if (e.Source is PasswordBox box) { string password = box.Password; } }
@chucker Thanks for your comment ☕
Yes you got it, but, you know what, if you wanna using MVVM
to binding field TEXT
to control the view, it still doesn't work, cause it will show double values when you perform some change in ViewModel
.
So, could you please have a further check?
Thanks
@pomianowski Could you please have a look? Thanks
I don't think WPFUI's PasswordBox
properly supports binding to the password at this point.
Instead, I use use WPFUI's control (but do use WPFUI's styling).
First, a utility class (I didn't write this; I think it originated at http://blog.functionalfun.net/2008/06/wpf-passwordbox-and-data-binding.html):
using System.Windows;
using System.Windows.Controls;
namespace Chucker.WpfUtils
{
public static class PasswordBoxAssistant
{
public static readonly DependencyProperty BoundPassword =
DependencyProperty.RegisterAttached("BoundPassword", typeof(string), typeof(PasswordBoxAssistant), new PropertyMetadata(string.Empty, OnBoundPasswordChanged));
public static readonly DependencyProperty BindPassword = DependencyProperty.RegisterAttached(
"BindPassword", typeof(bool), typeof(PasswordBoxAssistant), new PropertyMetadata(false, OnBindPasswordChanged));
private static readonly DependencyProperty UpdatingPassword =
DependencyProperty.RegisterAttached("UpdatingPassword", typeof(bool), typeof(PasswordBoxAssistant), new PropertyMetadata(false));
private static void OnBoundPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
PasswordBox box = d as PasswordBox;
// only handle this event when the property is attached to a PasswordBox
// and when the BindPassword attached property has been set to true
if (d == null || !GetBindPassword(d))
{
return;
}
// avoid recursive updating by ignoring the box's changed event
box.PasswordChanged -= HandlePasswordChanged;
string newPassword = (string)e.NewValue;
if (!GetUpdatingPassword(box))
{
box.Password = newPassword;
}
box.PasswordChanged += HandlePasswordChanged;
}
private static void OnBindPasswordChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
{
// when the BindPassword attached property is set on a PasswordBox,
// start listening to its PasswordChanged event
if (dp is not PasswordBox box)
{
return;
}
bool wasBound = (bool)(e.OldValue);
bool needToBind = (bool)(e.NewValue);
if (wasBound)
{
box.PasswordChanged -= HandlePasswordChanged;
}
if (needToBind)
{
box.PasswordChanged += HandlePasswordChanged;
}
}
private static void HandlePasswordChanged(object sender, RoutedEventArgs e)
{
PasswordBox box = sender as PasswordBox;
// set a flag to indicate that we're updating the password
SetUpdatingPassword(box, true);
// push the new password into the BoundPassword property
SetBoundPassword(box, box.Password);
SetUpdatingPassword(box, false);
}
public static void SetBindPassword(DependencyObject dp, bool value)
{
dp.SetValue(BindPassword, value);
}
public static bool GetBindPassword(DependencyObject dp)
{
return (bool)dp.GetValue(BindPassword);
}
public static string GetBoundPassword(DependencyObject dp)
{
return (string)dp.GetValue(BoundPassword);
}
public static void SetBoundPassword(DependencyObject dp, string value)
{
dp.SetValue(BoundPassword, value);
}
private static bool GetUpdatingPassword(DependencyObject dp)
{
return (bool)dp.GetValue(UpdatingPassword);
}
private static void SetUpdatingPassword(DependencyObject dp, bool value)
{
dp.SetValue(UpdatingPassword, value);
}
}
}
Then I can do:
<PasswordBox wpfutils:PasswordBoxAssistant.BindPassword="True"
wpfutils:PasswordBoxAssistant.BoundPassword="{Binding MyPassword, Mode=TwoWay}"
Now you just have a regular string
INPC property in your view model, e.g.
private string _MyPassword = "";
public string MyPassword
{
get => _MyPassword;
set => SetProperty(ref _MyPassword, value);
}
@chucker Thanks bro.
Yes you are right, I know the alt way to make the PosswordBox
works just like you posted.
But I still wanna the WPF-UI
have this feature just like this in convenience.
Hey @JeremyWu917, the Password
property of the PasswordBox
, should allow two-way binding in the current development branch.
@pomianowski Noted, thanks ☕
Hey @JeremyWu917, the
Password
property of thePasswordBox
, should allow two-way binding in the current development branch.
@pomianowski
Sorry for the late response, after review and check, here is NEW issue about PlaceholderText
as below gif.
-
PlaceholderText
can not disappear whenIsPasswordRevealed
is true -
PlaceholderText
disappeared for ever when you clear the value
Thanks