你必須努力PasswordBox的密碼屬性綁定到你的ViewModel財產。密碼屬性不可綁定,因爲它不是一個DependencyProperty。這是出於安全原因。
但是,如果您想使其可綁定,則必須使用自定義的AttachedProperty。現在,您正試圖通過按ATM機器上的按鈕來輸入PIN碼,並希望您的密碼也可以被綁定。看到下面的示例,讓你開始。
XAML代碼:
<Window x:Class="WpfEvents._32802407.Win32802407"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:pwd="clr-namespace:PasswordExtras"
Title="Win32802407" Height="354.136" Width="385.714">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="143*"/>
<ColumnDefinition Width="46*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="16*"/>
<RowDefinition Height="19*"/>
<RowDefinition Height="32*"/>
<RowDefinition Height="95*"/>
</Grid.RowDefinitions>
<TextBlock TextWrapping="Wrap" Text="Welcome Joshua !" FontSize="18" VerticalAlignment="Center" Margin="10,4,0,4"/>
<PasswordBox x:Name="pbPin" pwd:PasswordBoxAssistant.BindPassword="True" pwd:PasswordBoxAssistant.BoundPassword="{Binding Path=PIN, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" Grid.Row="2" VerticalAlignment="Center" Width="120" FontSize="18" BorderThickness="0"/>
<StackPanel Grid.Column="1" HorizontalAlignment="Left" Height="170" Margin="10,10,0,0" Grid.Row="3" VerticalAlignment="Top" Width="72">
<Button Content="Done" Margin="0,15,0,0" Height="31"/>
<Button Content="Clear" Margin="0,15,0,0" Height="31"/>
<Button Content="Cancel" Margin="0,15,0,0" Height="31"/>
</StackPanel>
<WrapPanel ButtonBase.Click="NumericButtons_Click" HorizontalAlignment="Left" Height="147" Margin="10,23,0,0" Grid.Row="3" VerticalAlignment="Top" Width="266">
<Button Content="1" Width="75" Margin="5" Height="25"/>
<Button Content="2" Width="75" Margin="5" Height="25"/>
<Button Content="3" Width="75" Margin="5" Height="25"/>
<Button Content="4" Width="75" Margin="5" Height="25"/>
<Button Content="5" Width="75" Margin="5" Height="25"/>
<Button Content="6" Width="75" Margin="5" Height="25"/>
<Button Content="7" Width="75" Margin="5" Height="25"/>
<Button Content="8" Width="75" Margin="5" Height="25"/>
<Button Content="9" Width="75" Margin="5" Height="25"/>
<Button Content="0" Width="75" Margin="5" Height="25"/>
</WrapPanel>
<TextBlock HorizontalAlignment="Left" Margin="23,9,0,0" Grid.Row="1" TextWrapping="Wrap" Text="Enter your pin or press cancel" VerticalAlignment="Top"/>
</Grid>
</Window>
XAML代碼隱藏:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Diagnostics;
namespace WpfEvents._32802407
{
/// <summary>
/// Interaction logic for Win32802407.xaml
/// </summary>
public partial class Win32802407 : Window
{
ViewModelATM atm = new ViewModelATM();
public Win32802407()
{
InitializeComponent();
this.DataContext = atm;
}
private void NumericButtons_Click(object sender, RoutedEventArgs e)
{
string pwd = PasswordExtras.PasswordBoxAssistant.GetBoundPassword(pbPin);
if (pwd.Length == 4)
{
e.Handled = true;
return;
}
pwd = pwd + ((Button)e.OriginalSource).Content;
PasswordExtras.PasswordBoxAssistant.SetBoundPassword(pbPin, pwd);
Debug.WriteLine(pwd + " : " + atm.PIN);
}
}
}
namespace PasswordExtras
{
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
PasswordBox box = dp as PasswordBox;
if (box == null)
{
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);
}
}
}
視圖模型
using System;
namespace WpfEvents._32802407
{
public class ViewModelATM
{
string _pin = "";
public string PIN { get { return _pin; } set { _pin = value; } }
}
}
你提到視圖模型。你想要做MVVM嗎?如果是這樣你不會使用Button.Click事件。 – KornMuffin