mirror of https://github.com/AMT-Cheif/Stylet.git
Use PasswordBoxes in Stylet.Samples.ModelValidation
This commit is contained in:
parent
6b2c8d9583
commit
ba8d5f338c
|
@ -24,13 +24,18 @@ namespace Stylet.Samples.ModelValidation
|
||||||
|
|
||||||
public async Task<string[]> ValidatePropertyAsync(string propertyName)
|
public async Task<string[]> ValidatePropertyAsync(string propertyName)
|
||||||
{
|
{
|
||||||
return (await this.validator.ValidateAsync(this.subject, propertyName)).Errors.Select(x => x.ErrorMessage).ToArray();
|
// If someone's calling us synchronously, and ValidationAsync does not complete synchronously,
|
||||||
|
// we'll deadlock unless we continue on another thread.
|
||||||
|
return (await this.validator.ValidateAsync(this.subject, propertyName).ConfigureAwait(false))
|
||||||
|
.Errors.Select(x => x.ErrorMessage).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Dictionary<string, string[]>> ValidateAllPropertiesAsync()
|
public async Task<Dictionary<string, string[]>> ValidateAllPropertiesAsync()
|
||||||
{
|
{
|
||||||
return (await this.validator.ValidateAsync(this.subject)).Errors
|
// If someone's calling us synchronously, and ValidationAsync does not complete synchronously,
|
||||||
.GroupBy(x => x.PropertyName)
|
// we'll deadlock unless we continue on another thread.
|
||||||
|
return (await this.validator.ValidateAsync(this.subject).ConfigureAwait(false))
|
||||||
|
.Errors.GroupBy(x => x.PropertyName)
|
||||||
.ToDictionary(x => x.Key, x => x.Select(failure => failure.ErrorMessage).ToArray());
|
.ToDictionary(x => x.Key, x => x.Select(failure => failure.ErrorMessage).ToArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:s="https://github.com/canton7/Stylet"
|
xmlns:s="https://github.com/canton7/Stylet"
|
||||||
|
xmlns:xaml="clr-namespace:Stylet.Samples.ModelValidation.Xaml"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="300" d:DesignWidth="300">
|
d:DesignHeight="300" d:DesignWidth="300">
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
|
@ -11,7 +12,7 @@
|
||||||
<Setter Property="Margin" Value="5,0,5,0" />
|
<Setter Property="Margin" Value="5,0,5,0" />
|
||||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style TargetType="{x:Type TextBox}">
|
<Style x:Key="CommonStyle" TargetType="{x:Type Control}">
|
||||||
<Setter Property="VerticalAlignment" Value="Center" />
|
<Setter Property="VerticalAlignment" Value="Center" />
|
||||||
<Setter Property="Margin" Value="0,2,40,20" />
|
<Setter Property="Margin" Value="0,2,40,20" />
|
||||||
<Setter Property="Validation.ErrorTemplate">
|
<Setter Property="Validation.ErrorTemplate">
|
||||||
|
@ -33,6 +34,8 @@
|
||||||
</Setter.Value>
|
</Setter.Value>
|
||||||
</Setter>
|
</Setter>
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource CommonStyle}"/>
|
||||||
|
<Style TargetType="{x:Type PasswordBox}" BasedOn="{StaticResource CommonStyle}"/>
|
||||||
</UserControl.Resources>
|
</UserControl.Resources>
|
||||||
|
|
||||||
<Grid Margin="10">
|
<Grid Margin="10">
|
||||||
|
@ -55,10 +58,10 @@
|
||||||
<TextBox Grid.Row="1" Grid.Column="1" x:Name="Email" Text="{Binding Email}"/>
|
<TextBox Grid.Row="1" Grid.Column="1" x:Name="Email" Text="{Binding Email}"/>
|
||||||
|
|
||||||
<Label Grid.Row="2" Grid.Column="0" Target="{Binding ElementName=Password}">Password:</Label>
|
<Label Grid.Row="2" Grid.Column="0" Target="{Binding ElementName=Password}">Password:</Label>
|
||||||
<TextBox Grid.Row="2" Grid.Column="1" x:Name="Password" Text="{Binding Password}"/>
|
<PasswordBox Grid.Row="2" Grid.Column="1" x:Name="Password" xaml:Secure.Password="{Binding Password}"/>
|
||||||
|
|
||||||
<Label Grid.Row="3" Grid.Column="0" Target="{Binding ElementName=PasswordConfirmation}">Password Confirmation:</Label>
|
<Label Grid.Row="3" Grid.Column="0" Target="{Binding ElementName=PasswordConfirmation}">Password Confirmation:</Label>
|
||||||
<TextBox Grid.Row="3" Grid.Column="1" x:Name="PasswordConfirmation" Text="{Binding PasswordConfirmation}"/>
|
<PasswordBox Grid.Row="3" Grid.Column="1" x:Name="PasswordConfirmation" xaml:Secure.Password="{Binding PasswordConfirmation}"/>
|
||||||
|
|
||||||
<CheckBox Grid.Row="4" Grid.Column="0" IsChecked="{Binding AutoValidate}">Auto-Validate</CheckBox>
|
<CheckBox Grid.Row="4" Grid.Column="0" IsChecked="{Binding AutoValidate}">Auto-Validate</CheckBox>
|
||||||
<Button Grid.Row="4" Grid.Column="1" Command="{s:Action Submit}" HorizontalAlignment="Left">Submit</Button>
|
<Button Grid.Row="4" Grid.Column="1" Command="{s:Action Submit}" HorizontalAlignment="Left">Submit</Button>
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
<DependentUpon>App.xaml</DependentUpon>
|
<DependentUpon>App.xaml</DependentUpon>
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Xaml\Secure.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Bootstrapper.cs" />
|
<Compile Include="Bootstrapper.cs" />
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Data;
|
||||||
|
|
||||||
|
namespace Stylet.Samples.ModelValidation.Xaml
|
||||||
|
{
|
||||||
|
public static class Secure
|
||||||
|
{
|
||||||
|
private static bool passwordInitialized;
|
||||||
|
private static bool settingPassword;
|
||||||
|
|
||||||
|
public static string GetPassword(DependencyObject obj)
|
||||||
|
{
|
||||||
|
return (string)obj.GetValue(PasswordProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetPassword(DependencyObject obj, string value)
|
||||||
|
{
|
||||||
|
obj.SetValue(PasswordProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using a DependencyProperty as the backing store for Password. This enables animation, styling, binding, etc...
|
||||||
|
public static readonly DependencyProperty PasswordProperty =
|
||||||
|
DependencyProperty.RegisterAttached("Password", typeof(string), typeof(Secure), new FrameworkPropertyMetadata(String.Empty, HandleBoundPasswordChanged)
|
||||||
|
{
|
||||||
|
BindsTwoWayByDefault = true,
|
||||||
|
DefaultUpdateSourceTrigger = UpdateSourceTrigger.LostFocus // Match the default on Binding
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
private static void HandleBoundPasswordChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (settingPassword)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var passwordBox = dp as PasswordBox;
|
||||||
|
if (passwordBox == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If this is the initial set
|
||||||
|
if (!passwordInitialized)
|
||||||
|
{
|
||||||
|
passwordInitialized = true;
|
||||||
|
passwordBox.PasswordChanged += HandlePasswordChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
passwordBox.Password = e.NewValue as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandlePasswordChanged(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var passwordBox = (PasswordBox)sender;
|
||||||
|
settingPassword = true;
|
||||||
|
SetPassword(passwordBox, passwordBox.Password);
|
||||||
|
settingPassword = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static bool securePasswordInitialized;
|
||||||
|
private static bool settingSecurePassword;
|
||||||
|
|
||||||
|
public static SecureString GetSecurePassword(DependencyObject obj)
|
||||||
|
{
|
||||||
|
return (SecureString)obj.GetValue(SecurePasswordProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SetSecurePassword(DependencyObject obj, SecureString value)
|
||||||
|
{
|
||||||
|
obj.SetValue(SecurePasswordProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly DependencyProperty SecurePasswordProperty =
|
||||||
|
DependencyProperty.RegisterAttached("SecurePassword", typeof(SecureString), typeof(Secure), new FrameworkPropertyMetadata(new SecureString(), HandleBoundSecurePasswordChanged) { BindsTwoWayByDefault = true });
|
||||||
|
|
||||||
|
|
||||||
|
private static void HandleBoundSecurePasswordChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (settingSecurePassword)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var passwordBox = dp as PasswordBox;
|
||||||
|
if (passwordBox == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!securePasswordInitialized)
|
||||||
|
{
|
||||||
|
passwordBox.PasswordChanged += HandleSecurePasswordChanged;
|
||||||
|
securePasswordInitialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandleSecurePasswordChanged(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var passwordBox = (PasswordBox)sender;
|
||||||
|
settingSecurePassword = true;
|
||||||
|
SetSecurePassword(passwordBox, passwordBox.SecurePassword);
|
||||||
|
settingSecurePassword = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue