I have a WPF
ListBox
, each ListBoxItem
has many UIElements
. One of those UIElements
is PasswordBox
. These UIElements
are defined in Xaml
ControlTemplate
.
What I need to do is get a Password
string from PasswordBox
in code behind. But I can not bind Password
Property of PasswordBox
, which is not a dynamic property and it make sense as Password
should not be stored in a memory for long.
Now the Solution that comes to my mind is to get UIElements
of ListBoxItem
in code behind and get Password
from there.
But I am unable to figure out how can i get the UIElements
in code behind from ListBox.
The Password property of the password box is not is dependency property, hence you can not bind this property.
You can us either of the following way to get the password from passwordbox control.
Pass the password box control as a parameter to the command attached with item.
XAML
<Window x:Class="WpfApplication4.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<StackPanel>
<PasswordBox Name="txtPassword" VerticalAlignment="Top" Width="120" />
<Button Content="Ok" Command="{Binding Path=OkCommand}" CommandParameter="{Binding ElementName=txtPassword}"/>
</StackPanel>
Code behind
public class MyViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
public ICommand OkCommand { get; private set; }
public MyViewModel()
{
OkCommand = new GeneralCommand<object>(ExecuteOkCommand, param => CanExecuteCommand());
}
private void ExecuteOkCommand(object parameter)
{
var passwordBox = parameter as PasswordBox;
var password = passwordBox.Password;
}
private bool CanExecuteCommand()
{
return true;
}
}
This slightly violates the MVVM pattern since now the viewmodel knows something about how the view is implemented.
- Use the attach property to bind the password.
XAML
<StackPanel>
<PasswordBox w:PasswordHelper.Attach="True"
w:PasswordHelper.Password="{Binding Text, ElementName=plain, Mode=TwoWay}"
Width="130"/>
<TextBlock Padding="10,0" x:Name="plain" />
</StackPanel>
Code
public static class PasswordHelper
{
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.RegisterAttached("Password",
typeof(string), typeof(PasswordHelper),
new FrameworkPropertyMetadata(string.Empty, OnPasswordPropertyChanged));
public static readonly DependencyProperty AttachProperty =
DependencyProperty.RegisterAttached("Attach",
typeof(bool), typeof(PasswordHelper), new PropertyMetadata(false, Attach));
private static readonly DependencyProperty IsUpdatingProperty =
DependencyProperty.RegisterAttached("IsUpdating", typeof(bool),
typeof(PasswordHelper));
public static void SetAttach(DependencyObject dp, bool value)
{
dp.SetValue(AttachProperty, value);
}
public static bool GetAttach(DependencyObject dp)
{
return (bool)dp.GetValue(AttachProperty);
}
public static string GetPassword(DependencyObject dp)
{
return (string)dp.GetValue(PasswordProperty);
}
public static void SetPassword(DependencyObject dp, string value)
{
dp.SetValue(PasswordProperty, value);
}
private static bool GetIsUpdating(DependencyObject dp)
{
return (bool)dp.GetValue(IsUpdatingProperty);
}
private static void SetIsUpdating(DependencyObject dp, bool value)
{
dp.SetValue(IsUpdatingProperty, value);
}
private static void OnPasswordPropertyChanged(DependencyObject sender,
DependencyPropertyChangedEventArgs e)
{
PasswordBox passwordBox = sender as PasswordBox;
passwordBox.PasswordChanged -= PasswordChanged;
if (!(bool)GetIsUpdating(passwordBox))
{
passwordBox.Password = (string)e.NewValue;
}
passwordBox.PasswordChanged += PasswordChanged;
}
private static void Attach(DependencyObject sender,
DependencyPropertyChangedEventArgs e)
{
PasswordBox passwordBox = sender as PasswordBox;
if (passwordBox == null)
return;
if ((bool)e.OldValue)
{
passwordBox.PasswordChanged -= PasswordChanged;
}
if ((bool)e.NewValue)
{
passwordBox.PasswordChanged += PasswordChanged;
}
}
private static void PasswordChanged(object sender, RoutedEventArgs e)
{
PasswordBox passwordBox = sender as PasswordBox;
SetIsUpdating(passwordBox, true);
SetPassword(passwordBox, passwordBox.Password);
SetIsUpdating(passwordBox, false);
}
}
You can refer the "http://wpftutorial.net/PasswordBox.html" for detail information.