我有一个WPF
ListBox
,每个ListBoxItem
有多个UIElements
。其中一个UIElements
是PasswordBox
。这些UIElements
在Xaml
ControlTemplate
中定义。
我需要做的是在后面的代码中从Password
获取PasswordBox
字符串。但我无法绑定Password
的{{1}}属性,它不是动态属性,因为PasswordBox
不应该长时间存储在内存中。
现在我想到的解决方案是让Password
的{{1}}代码落后并从那里获得UIElements
。
但我无法弄清楚如何从ListBox中获取代码中的ListBoxItem
。
答案 0 :(得分:3)
密码框的密码属性不是依赖属性,因此您无法绑定此属性。
您可以通过以下任一方式从密码箱控件获取密码。
将密码框控件作为参数传递给附带项目的命令。
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>
代码
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;
}
}
这略微违反了MVVM模式,因为现在viewmodel知道视图是如何实现的。
<强> 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>
代码
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);
}
}
您可以参考“http://wpftutorial.net/PasswordBox.html”了解详细信息。