enhance the function of passwordbox

This commit is contained in:
NaBian committed 2018-11-18 00:10:10 +08:00
1 parent aece5e3a44
commit 368fb52ed4
15 files changed
+481 -94

No files matched your search

+2 -2
View File
@@ -20,7 +20,7 @@ namespace HandyControl.Controls
/// 占位符
/// </summary>
public static readonly DependencyProperty PlaceholderProperty = DependencyProperty.RegisterAttached(
"Placeholder", typeof(string), typeof(InfoElement), new PropertyMetadata(default(string)));
"Placeholder", typeof(string), typeof(InfoElement), new FrameworkPropertyMetadata(default(string), FrameworkPropertyMetadataOptions.Inherits));
public static void SetPlaceholder(DependencyObject element, string value) => element.SetValue(PlaceholderProperty, value);
@@ -70,7 +70,7 @@ namespace HandyControl.Controls
/// 内容高度
/// </summary>
public static readonly DependencyProperty ContentHeightProperty = DependencyProperty.RegisterAttached(
"ContentHeight", typeof(double), typeof(InfoElement), new PropertyMetadata(30.0));
"ContentHeight", typeof(double), typeof(InfoElement), new FrameworkPropertyMetadata(30.0, FrameworkPropertyMetadataOptions.Inherits));
public static void SetContentHeight(DependencyObject element, double value) => element.SetValue(ContentHeightProperty, value);
@@ -1,5 +1,4 @@
using System.Windows;
using System.Windows.Controls;
using HandyControl.Data;
// ReSharper disable once CheckNamespace
@@ -25,7 +24,7 @@ namespace HandyControl.Controls
private static void OnIsMonitoringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is PasswordBox passwordBox)
if (d is System.Windows.Controls.PasswordBox passwordBox)
{
if (e.NewValue is bool boolValue)
{
@@ -47,7 +46,7 @@ namespace HandyControl.Controls
private static void PasswordChanged(object sender, RoutedEventArgs e)
{
if (sender is PasswordBox passwordBox)
if (sender is System.Windows.Controls.PasswordBox passwordBox)
{
SetPasswordLength(passwordBox, passwordBox.Password.Length);
}
+172
View File
@@ -0,0 +1,172 @@
using System;
using System.ComponentModel;
using System.Security;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using HandyControl.Data;
using HandyControl.Interactivity;
using HandyControl.Properties.Langs;
namespace HandyControl.Controls
{
/// <inheritdoc cref="IDataInput" />
public class PasswordBox : Control, IDataInput
{
private const string ElementPasswordBox = "PART_PasswordBox";
/// <summary>
/// 掩码字符
/// </summary>
public static readonly DependencyProperty PasswordCharProperty =
System.Windows.Controls.PasswordBox.PasswordCharProperty.AddOwner(typeof(PasswordBox),
new FrameworkPropertyMetadata('●'));
/// <summary>
/// 数据是否错误
/// </summary>
public static readonly DependencyProperty IsErrorProperty = DependencyProperty.Register(
"IsError", typeof(bool), typeof(PasswordBox), new PropertyMetadata(default(bool)));
/// <summary>
/// 错误提示
/// </summary>
public static readonly DependencyProperty ErrorStrProperty = DependencyProperty.Register(
"ErrorStr", typeof(string), typeof(PasswordBox), new PropertyMetadata(default(string)));
/// <summary>
/// 文本类型
/// </summary>
public static readonly DependencyProperty TextTypeProperty = DependencyProperty.Register(
"TextType", typeof(TextType), typeof(PasswordBox), new PropertyMetadata(default(TextType)));
/// <summary>
/// 是否显示清除按钮
/// </summary>
public static readonly DependencyProperty ShowClearButtonProperty = DependencyProperty.Register(
"ShowClearButton", typeof(bool), typeof(PasswordBox), new PropertyMetadata(default(bool)));
private string _password;
private char _passwordChar;
public PasswordBox()
{
CommandBindings.Add(new CommandBinding(ControlCommands.Clear, (s, e) => ActualPasswordBox.Clear()));
}
public System.Windows.Controls.PasswordBox ActualPasswordBox { get; set; }
[DefaultValue("")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string Password
{
get => ActualPasswordBox?.Password;
set
{
if (ActualPasswordBox == null)
{
_password = value;
return;
}
ActualPasswordBox.Password = value;
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public SecureString SecurePassword => ActualPasswordBox?.SecurePassword;
public char PasswordChar
{
get => (char) GetValue(PasswordCharProperty);
set => SetValue(PasswordCharProperty, value);
}
public Func<string, OperationResult<bool>> VerifyFunc { get; set; }
public bool IsError
{
get => (bool) GetValue(IsErrorProperty);
set => SetValue(IsErrorProperty, value);
}
public string ErrorStr
{
get => (string) GetValue(ErrorStrProperty);
set => SetValue(ErrorStrProperty, value);
}
public TextType TextType
{
get => (TextType) GetValue(TextTypeProperty);
set => SetValue(TextTypeProperty, value);
}
public bool ShowClearButton
{
get => (bool) GetValue(ShowClearButtonProperty);
set => SetValue(ShowClearButtonProperty, value);
}
public virtual bool VerifyData()
{
OperationResult<bool> result;
if (VerifyFunc != null)
{
result = VerifyFunc.Invoke(ActualPasswordBox.Password);
}
else
{
if (!string.IsNullOrEmpty(ActualPasswordBox.Password))
result = OperationResult.Success();
else if (InfoElement.GetNecessary(this))
result = OperationResult.Failed(Lang.IsNecessary);
else
result = OperationResult.Success();
}
IsError = !result.Data;
ErrorStr = result.Message;
return result.Data;
}
public override void OnApplyTemplate()
{
if (ActualPasswordBox != null)
ActualPasswordBox.PasswordChanged -= PasswordBox_PasswordChanged;
base.OnApplyTemplate();
ActualPasswordBox = GetTemplateChild(ElementPasswordBox) as System.Windows.Controls.PasswordBox;
if (ActualPasswordBox != null)
{
ActualPasswordBox.PasswordChanged += PasswordBox_PasswordChanged;
if (!string.IsNullOrEmpty(_password))
{
ActualPasswordBox.Password = _password;
_password = null;
}
if (_passwordChar != default(char))
{
ActualPasswordBox.PasswordChar = _passwordChar;
_passwordChar = default(char);
}
}
}
public void Paste() => ActualPasswordBox.Paste();
public void SelectAll() => ActualPasswordBox.SelectAll();
public void Clear() => ActualPasswordBox.SelectAll();
private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
{
VerifyData();
}
}
}
-1
View File
@@ -6,7 +6,6 @@ using HandyControl.Data;
using HandyControl.Interactivity;
using HandyControl.Tools;
// ReSharper disable once CheckNamespace
namespace HandyControl.Controls
{
/// <inheritdoc cref="IDataInput" />
+1
View File
@@ -54,6 +54,7 @@
<Compile Include="Controls\ImageViewer.cs" />
<Compile Include="Controls\Input\ComboBox.cs" />
<Compile Include="Controls\Input\IDataInput.cs" />
<Compile Include="Controls\Input\PasswordBox.cs" />
<Compile Include="Controls\Input\TextBox.cs" />
<Compile Include="Controls\ISingleOpen.cs" />
<Compile Include="Controls\Input\NumericUpDown.cs" />
@@ -1,7 +1,16 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:HandyControl.Controls">
xmlns:controls="clr-namespace:HandyControl.Controls"
xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:interactivity="clr-namespace:HandyControl.Interactivity">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../../Basic/Converters.xaml"/>
<ResourceDictionary Source="../../Basic/Geometries.xaml"/>
<ResourceDictionary Source="../TextBlock.xaml"/>
<ResourceDictionary Source="../Button.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="PasswordBoxBaseStyle" TargetType="PasswordBox">
<Setter Property="Background" Value="{DynamicResource RegionBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
@@ -40,4 +49,241 @@
</Setter>
</Style>
<ControlTemplate x:Key="PasswordBoxExtendTopTemplate" TargetType="PasswordBox">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="{Binding Path=(controls:InfoElement.ContentHeight),RelativeSource={RelativeSource TemplatedParent}}"/>
</Grid.RowDefinitions>
<StackPanel Visibility="{Binding Path=(controls:InfoElement.Title),RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource String2VisibilityConverter}}" Orientation="Horizontal" Margin="7,4">
<TextBlock Margin="1,0,0,0" Text="{Binding Path=(controls:InfoElement.Title),RelativeSource={RelativeSource TemplatedParent}}"/>
<ContentPresenter TextElement.Foreground="{DynamicResource DangerBrush}" Margin="4,0,0,0" Content="{Binding Path=(controls:InfoElement.Symbol),RelativeSource={RelativeSource TemplatedParent}}" Visibility="{Binding Path=(controls:InfoElement.Necessary),RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource Boolean2VisibilityConverter}}"/>
</StackPanel>
<Border x:Name="border" Grid.Row="1" CornerRadius="{Binding Path=(controls:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"/>
<TextBlock x:Name="placeholder" Visibility="Collapsed" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="8" Grid.Row="1" HorizontalAlignment="Stretch" Style="{StaticResource TextBlockDefaultThiLight}" Text="{Binding Path=(controls:InfoElement.Placeholder),RelativeSource={RelativeSource TemplatedParent}}"/>
<ScrollViewer Padding="6,0" Margin="0,1,0,2" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" Grid.Row="1" x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="controls:PasswordBoxMonitor.PasswordLength" Value="0">
<Setter Property="Visibility" TargetName="placeholder" Value="Visible"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" Value="0.4"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true" SourceName="PART_ContentHost">
<Setter Property="BorderBrush" Value="{DynamicResource SecondaryBorderBrush}"/>
</Trigger>
<Trigger Property="IsFocused" Value="true">
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="PasswordBoxExtendLeftTemplate" TargetType="PasswordBox">
<Grid Height="{Binding Path=(controls:InfoElement.ContentHeight),RelativeSource={RelativeSource TemplatedParent}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding Path=(controls:InfoElement.TitleWidth),RelativeSource={RelativeSource TemplatedParent}}"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel Visibility="{Binding Path=(controls:InfoElement.Title),RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource String2VisibilityConverter}}" Orientation="Horizontal" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="0,7,6,8">
<TextBlock Text="{Binding Path=(controls:InfoElement.Title),RelativeSource={RelativeSource TemplatedParent}}"/>
<ContentPresenter TextElement.Foreground="{DynamicResource DangerBrush}" Margin="4,0,0,0" Content="{Binding Path=(controls:InfoElement.Symbol),RelativeSource={RelativeSource TemplatedParent}}" Visibility="{Binding Path=(controls:InfoElement.Necessary),RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource Boolean2VisibilityConverter}}"/>
</StackPanel>
<Border x:Name="border" Grid.Column="1" CornerRadius="{Binding Path=(controls:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"/>
<TextBlock VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="8,7,8,8" x:Name="placeholder" Visibility="Collapsed" Grid.Column="1" HorizontalAlignment="Stretch" Style="{StaticResource TextBlockDefaultThiLight}" Text="{Binding Path=(controls:InfoElement.Placeholder),RelativeSource={RelativeSource TemplatedParent}}"/>
<ScrollViewer Grid.Column="1" Padding="7,0" Margin="0,1,0,2" x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="controls:PasswordBoxMonitor.PasswordLength" Value="0">
<Setter Property="Visibility" TargetName="placeholder" Value="Visible"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" Value="0.4"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true" SourceName="PART_ContentHost">
<Setter Property="BorderBrush" Value="{DynamicResource SecondaryBorderBrush}"/>
</Trigger>
<Trigger Property="IsFocused" Value="true">
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="PasswordBoxExtendBaseStyle" BasedOn="{StaticResource PasswordBoxBaseStyle}" TargetType="PasswordBox">
<Setter Property="Height" Value="{x:Static system:Double.NaN}"/>
<Setter Property="Padding" Value="7,6"/>
<Setter Property="controls:InfoElement.Symbol" Value="●"/>
<Setter Property="controls:InfoElement.ContentHeight" Value="30.0"/>
<Setter Property="controls:PasswordBoxMonitor.IsMonitoring" Value="True"/>
<Setter Property="Template" Value="{StaticResource PasswordBoxExtendTopTemplate}"/>
<Style.Triggers>
<Trigger Property="controls:InfoElement.TitleAlignment" Value="Left">
<Setter Property="Template" Value="{StaticResource PasswordBoxExtendLeftTemplate}"/>
<Setter Property="Width" Value="{x:Static system:Double.NaN}"/>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="PasswordBoxPlusInternalStyle" TargetType="PasswordBox">
<Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="Height" Value="30"/>
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="7,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="PasswordBox">
<Grid>
<Border x:Name="border" CornerRadius="{Binding Path=(controls:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"/>
<TextBlock VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="8,7,8,8" x:Name="placeholder" Visibility="Collapsed" HorizontalAlignment="Stretch" Style="{StaticResource TextBlockDefaultThiLight}" Text="{Binding Path=(controls:InfoElement.Placeholder),RelativeSource={RelativeSource TemplatedParent}}"/>
<ScrollViewer Padding="{TemplateBinding Padding}" Margin="0,1,0,2" x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="controls:PasswordBoxMonitor.PasswordLength" Value="0">
<Setter Property="Visibility" TargetName="placeholder" Value="Visible"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" Value="0.4"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="PasswordBoxPlusTopTemplate" TargetType="controls:PasswordBox">
<ControlTemplate.Resources>
<Storyboard x:Key="StoryboardShow">
<ThicknessAnimation Storyboard.TargetName="TextBlockError" Storyboard.TargetProperty="Margin" To="8,0,0,-18" Duration="0:0:.2"/>
</Storyboard>
<Storyboard x:Key="StoryboardHidden">
<ThicknessAnimation Storyboard.TargetName="TextBlockError" Storyboard.TargetProperty="Margin" To="8,0,0,4" Duration="0:0:0"/>
</Storyboard>
</ControlTemplate.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="{Binding Path=(controls:InfoElement.ContentHeight),RelativeSource={RelativeSource TemplatedParent}}"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto" MinWidth="30"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.ColumnSpan="2" Visibility="{Binding Path=(controls:InfoElement.Title),RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource String2VisibilityConverter}}" Orientation="Horizontal" Margin="7,4">
<TextBlock Margin="1,0,0,0" Text="{Binding Path=(controls:InfoElement.Title),RelativeSource={RelativeSource TemplatedParent}}"/>
<ContentPresenter TextElement.Foreground="{DynamicResource DangerBrush}" Margin="4,0,0,0" Content="{Binding Path=(controls:InfoElement.Symbol),RelativeSource={RelativeSource TemplatedParent}}" Visibility="{Binding Path=(controls:InfoElement.Necessary),RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource Boolean2VisibilityConverter}}"/>
</StackPanel>
<TextBlock Grid.Column="0" Grid.ColumnSpan="2" Text="{TemplateBinding ErrorStr}" Name="TextBlockError" VerticalAlignment="Bottom" Margin="8,0,0,4" Foreground="{DynamicResource DangerBrush}" Grid.Row="1"/>
<PasswordBox BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" Foreground="{TemplateBinding Foreground}" BorderThickness="{TemplateBinding BorderThickness}" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" x:Name="PART_PasswordBox" PasswordChar="{TemplateBinding PasswordChar}" Style="{StaticResource PasswordBoxPlusInternalStyle}"/>
<Button Grid.Row="1" Grid.Column="1" Command="interactivity:ControlCommands.Clear" Margin="0,0,7,0" Visibility="Collapsed" Name="ButtonClear" Width="16" Style="{StaticResource ButtonIcon}" Padding="0,6" controls:IconElement.Geometry="{StaticResource DeleteFillCircleGeometry}" Foreground="{Binding BorderBrush,ElementName=PART_PasswordBox}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" Value="{DynamicResource SecondaryBorderBrush}"/>
</Trigger>
<Trigger Property="IsFocused" Value="true" SourceName="PART_PasswordBox">
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryBrush}"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="true"/>
<Condition Property="ShowClearButton" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" Value="Visible" TargetName="ButtonClear"/>
<Setter Property="Padding" Value="7,0,30,0" TargetName="PART_PasswordBox"/>
</MultiTrigger>
<Trigger Property="IsError" Value="true">
<Setter Property="BorderBrush" Value="{DynamicResource DangerBrush}"/>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource StoryboardShow}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource StoryboardHidden}"/>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="PasswordBoxPlusLeftTemplate" TargetType="controls:PasswordBox">
<ControlTemplate.Resources>
<Storyboard x:Key="StoryboardShow">
<ThicknessAnimation Storyboard.TargetName="TextBlockError" Storyboard.TargetProperty="Margin" To="8,0,0,-18" Duration="0:0:.2"/>
</Storyboard>
<Storyboard x:Key="StoryboardHidden">
<ThicknessAnimation Storyboard.TargetName="TextBlockError" Storyboard.TargetProperty="Margin" To="8,0,0,4" Duration="0:0:0"/>
</Storyboard>
</ControlTemplate.Resources>
<Grid Height="{Binding Path=(controls:InfoElement.ContentHeight),RelativeSource={RelativeSource TemplatedParent}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding Path=(controls:InfoElement.TitleWidth),RelativeSource={RelativeSource TemplatedParent}}"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto" MinWidth="30"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Visibility="{Binding Path=(controls:InfoElement.Title),RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource String2VisibilityConverter}}" Orientation="Horizontal" Margin="0,7,6,8">
<TextBlock Margin="1,0,0,0" Text="{Binding Path=(controls:InfoElement.Title),RelativeSource={RelativeSource TemplatedParent}}"/>
<ContentPresenter TextElement.Foreground="{DynamicResource DangerBrush}" Margin="4,0,0,0" Content="{Binding Path=(controls:InfoElement.Symbol),RelativeSource={RelativeSource TemplatedParent}}" Visibility="{Binding Path=(controls:InfoElement.Necessary),RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource Boolean2VisibilityConverter}}"/>
</StackPanel>
<TextBlock Grid.ColumnSpan="2" Text="{TemplateBinding ErrorStr}" Name="TextBlockError" VerticalAlignment="Bottom" Margin="8,0,0,4" Foreground="{DynamicResource DangerBrush}" Grid.Column="1"/>
<PasswordBox BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" Foreground="{TemplateBinding Foreground}" BorderThickness="{TemplateBinding BorderThickness}" Grid.Column="1" Grid.ColumnSpan="2" x:Name="PART_PasswordBox" PasswordChar="{TemplateBinding PasswordChar}" Style="{StaticResource PasswordBoxPlusInternalStyle}"/>
<Button Grid.Column="2" Command="interactivity:ControlCommands.Clear" Margin="0,0,7,0" Visibility="Collapsed" Name="ButtonClear" Width="16" Style="{StaticResource ButtonIcon}" Padding="0,6" controls:IconElement.Geometry="{StaticResource DeleteFillCircleGeometry}" Foreground="{Binding BorderBrush,ElementName=PART_PasswordBox}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" Value="{DynamicResource SecondaryBorderBrush}"/>
</Trigger>
<Trigger Property="IsFocused" Value="true" SourceName="PART_PasswordBox">
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryBrush}"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="true"/>
<Condition Property="ShowClearButton" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" Value="Visible" TargetName="ButtonClear"/>
<Setter Property="Padding" Value="7,0,30,0" TargetName="PART_PasswordBox"/>
</MultiTrigger>
<Trigger Property="IsError" Value="true">
<Setter Property="BorderBrush" Value="{DynamicResource DangerBrush}"/>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource StoryboardShow}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource StoryboardHidden}"/>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="PasswordBoxPlusBaseStyle" TargetType="controls:PasswordBox">
<Setter Property="Background" Value="{DynamicResource RegionBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="controls:BorderElement.CornerRadius" Value="4"/>
<Setter Property="PasswordChar" Value="●"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="AllowDrop" Value="true"/>
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Height" Value="{x:Static system:Double.NaN}"/>
<Setter Property="Padding" Value="7,6"/>
<Setter Property="controls:InfoElement.Symbol" Value="●"/>
<Setter Property="controls:InfoElement.ContentHeight" Value="30.0"/>
<Setter Property="controls:PasswordBoxMonitor.IsMonitoring" Value="True"/>
<Setter Property="Focusable" Value="False"/>
<Setter Property="Template" Value="{StaticResource PasswordBoxPlusTopTemplate}"/>
<Style.Triggers>
<Trigger Property="controls:InfoElement.TitleAlignment" Value="Left">
<Setter Property="Template" Value="{StaticResource PasswordBoxPlusLeftTemplate}"/>
<Setter Property="Width" Value="{x:Static system:Double.NaN}"/>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
+3 -77
View File
@@ -1,89 +1,15 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:HandyControl.Controls"
xmlns:system="clr-namespace:System;assembly=mscorlib">
xmlns:controls="clr-namespace:HandyControl.Controls">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Basic/Converters.xaml"/>
<ResourceDictionary Source="Base/PasswordBoxBaseStyle.xaml"/>
<ResourceDictionary Source="TextBlock.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style BasedOn="{StaticResource PasswordBoxBaseStyle}" TargetType="PasswordBox"/>
<ControlTemplate x:Key="PasswordBoxExtendTopTemplate" TargetType="PasswordBox">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="{Binding Path=(controls:InfoElement.ContentHeight),RelativeSource={RelativeSource TemplatedParent}}"/>
</Grid.RowDefinitions>
<StackPanel Visibility="{Binding Path=(controls:InfoElement.Title),RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource String2VisibilityConverter}}" Orientation="Horizontal" Margin="7,4">
<TextBlock Margin="1,0,0,0" Text="{Binding Path=(controls:InfoElement.Title),RelativeSource={RelativeSource TemplatedParent}}"/>
<ContentPresenter TextElement.Foreground="{DynamicResource DangerBrush}" Margin="4,0,0,0" Content="{Binding Path=(controls:InfoElement.Symbol),RelativeSource={RelativeSource TemplatedParent}}" Visibility="{Binding Path=(controls:InfoElement.Necessary),RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource Boolean2VisibilityConverter}}"/>
</StackPanel>
<Border x:Name="border" Grid.Row="1" CornerRadius="{Binding Path=(controls:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"/>
<TextBlock x:Name="placeholder" Visibility="Collapsed" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="8" Grid.Row="1" HorizontalAlignment="Stretch" Style="{StaticResource TextBlockDefaultThiLight}" Text="{Binding Path=(controls:InfoElement.Placeholder),RelativeSource={RelativeSource TemplatedParent}}"/>
<ScrollViewer Padding="6,0" Margin="0,1,0,2" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" Grid.Row="1" x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="controls:PasswordBoxMonitor.PasswordLength" Value="0">
<Setter Property="Visibility" TargetName="placeholder" Value="Visible"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" TargetName="border" Value="0.4"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true" SourceName="PART_ContentHost">
<Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource SecondaryBorderBrush}"/>
</Trigger>
<Trigger Property="IsFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource PrimaryBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="PasswordBoxExtend" BasedOn="{StaticResource PasswordBoxExtendBaseStyle}" TargetType="PasswordBox"/>
<ControlTemplate x:Key="PasswordBoxExtendLeftTemplate" TargetType="PasswordBox">
<Grid Height="{Binding Path=(controls:InfoElement.ContentHeight),RelativeSource={RelativeSource TemplatedParent}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding Path=(controls:InfoElement.TitleWidth),RelativeSource={RelativeSource TemplatedParent}}"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel Visibility="{Binding Path=(controls:InfoElement.Title),RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource String2VisibilityConverter}}" Orientation="Horizontal" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="0,7,6,8">
<TextBlock Text="{Binding Path=(controls:InfoElement.Title),RelativeSource={RelativeSource TemplatedParent}}"/>
<ContentPresenter TextElement.Foreground="{DynamicResource DangerBrush}" Margin="4,0,0,0" Content="{Binding Path=(controls:InfoElement.Symbol),RelativeSource={RelativeSource TemplatedParent}}" Visibility="{Binding Path=(controls:InfoElement.Necessary),RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource Boolean2VisibilityConverter}}"/>
</StackPanel>
<Border x:Name="border" Grid.Column="1" CornerRadius="{Binding Path=(controls:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"/>
<TextBlock VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="8,7,8,8" x:Name="placeholder" Visibility="Collapsed" Grid.Column="1" HorizontalAlignment="Stretch" Style="{StaticResource TextBlockDefaultThiLight}" Text="{Binding Path=(controls:InfoElement.Placeholder),RelativeSource={RelativeSource TemplatedParent}}"/>
<ScrollViewer Grid.Column="1" Padding="7,0" Margin="0,1,0,2" x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="controls:PasswordBoxMonitor.PasswordLength" Value="0">
<Setter Property="Visibility" TargetName="placeholder" Value="Visible"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" TargetName="border" Value="0.4"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true" SourceName="PART_ContentHost">
<Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource SecondaryBorderBrush}"/>
</Trigger>
<Trigger Property="IsFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource PrimaryBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="PasswordBoxExtend" BasedOn="{StaticResource PasswordBoxBaseStyle}" TargetType="PasswordBox">
<Setter Property="Height" Value="{x:Static system:Double.NaN}"/>
<Setter Property="Padding" Value="7,6"/>
<Setter Property="controls:InfoElement.Symbol" Value="●"/>
<Setter Property="controls:InfoElement.ContentHeight" Value="30.0"/>
<Setter Property="controls:PasswordBoxMonitor.IsMonitoring" Value="True"/>
<Setter Property="Template" Value="{StaticResource PasswordBoxExtendTopTemplate}"/>
<Style.Triggers>
<Trigger Property="controls:InfoElement.TitleAlignment" Value="Left">
<Setter Property="Template" Value="{StaticResource PasswordBoxExtendLeftTemplate}"/>
<Setter Property="Width" Value="{x:Static system:Double.NaN}"/>
</Trigger>
</Style.Triggers>
</Style>
<Style BasedOn="{StaticResource PasswordBoxPlusBaseStyle}" TargetType="controls:PasswordBox"/>
</ResourceDictionary>
+3 -1
View File
@@ -42,6 +42,8 @@
public static readonly string ComboBoxDemoCtl = nameof(ComboBoxDemoCtl);
public static readonly string PasswordBoxDemoCtl = nameof(PasswordBoxDemoCtl);
public static readonly string ButtonDemoCtl = nameof(ButtonDemoCtl);
public static readonly string ToggleButtonDemoCtl = nameof(ToggleButtonDemoCtl);
@@ -62,7 +64,7 @@
public static readonly string NaiveComboBoxDemoCtl = nameof(NaiveComboBoxDemoCtl);
public static readonly string PasswordBoxDemoCtl = nameof(PasswordBoxDemoCtl);
public static readonly string NaivePasswordBoxDemoCtl = nameof(NaivePasswordBoxDemoCtl);
public static readonly string NaiveTabControlDemoCtl = nameof(NaiveTabControlDemoCtl);
+3 -2
View File
@@ -23,7 +23,8 @@ var controlList = new List<string>
"PreviewSliderDemoCtl",
"CircleProgressBarDemoCtl",
"TextBoxDemoCtl",
"ComboBoxDemoCtl"
"ComboBoxDemoCtl",
"PasswordBoxDemoCtl"
};
var styleList = new List<string>
{
@@ -37,7 +38,7 @@ var styleList = new List<string>
"NaiveTextBoxDemoCtl",
"TextBlockDemoCtl",
"NaiveComboBoxDemoCtl",
"PasswordBoxDemoCtl",
"NaivePasswordBoxDemoCtl",
"NaiveTabControlDemoCtl",
"DataGridDemoCtl",
"CheckBoxDemoCtl",
+10 -3
View File
@@ -132,6 +132,9 @@
<Compile Include="UserControl\Controls\NumericUpDownDemoCtl.xaml.cs">
<DependentUpon>NumericUpDownDemoCtl.xaml</DependentUpon>
</Compile>
<Compile Include="UserControl\Controls\PasswordBoxDemoCtl.xaml.cs">
<DependentUpon>PasswordBoxDemoCtl.xaml</DependentUpon>
</Compile>
<Compile Include="UserControl\Controls\PreviewSliderDemoCtl.xaml.cs">
<DependentUpon>PreviewSliderDemoCtl.xaml</DependentUpon>
</Compile>
@@ -207,8 +210,8 @@
<Compile Include="UserControl\Styles\NaiveTabControlDemoCtl.xaml.cs">
<DependentUpon>NaiveTabControlDemoCtl.xaml</DependentUpon>
</Compile>
<Compile Include="UserControl\Styles\PasswordBoxDemoCtl.xaml.cs">
<DependentUpon>PasswordBoxDemoCtl.xaml</DependentUpon>
<Compile Include="UserControl\Styles\NaivePasswordBoxDemoCtl.xaml.cs">
<DependentUpon>NaivePasswordBoxDemoCtl.xaml</DependentUpon>
</Compile>
<Compile Include="UserControl\Styles\ProgressBarDemoCtl.xaml.cs">
<DependentUpon>ProgressBarDemoCtl.xaml</DependentUpon>
@@ -357,6 +360,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UserControl\Controls\PasswordBoxDemoCtl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UserControl\Controls\PreviewSliderDemoCtl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -457,7 +464,7 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UserControl\Styles\PasswordBoxDemoCtl.xaml">
<Page Include="UserControl\Styles\NaivePasswordBoxDemoCtl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
@@ -0,0 +1,20 @@
<UserControl x:Class="HandyControlDemo.UserControl.PasswordBoxDemoCtl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:HandyControl.Controls;assembly=HandyControl"
xmlns:langs="clr-namespace:HandyControlDemo.Properties.Langs"
Background="{DynamicResource RegionBrush}">
<controls:TransitioningContentControl>
<StackPanel Margin="32">
<controls:PasswordBox ShowClearButton="True" Password="123456"/>
<controls:PasswordBox Password="123456" IsEnabled="False" Margin="0,16,0,0"/>
<controls:PasswordBox ShowClearButton="True" controls:InfoElement.Title="{x:Static langs:Lang.TitleDemoStr1}" Password="123456" Margin="0,32,0,0"/>
<controls:PasswordBox controls:InfoElement.Placeholder="{x:Static langs:Lang.PlsEnterContent}" controls:InfoElement.Title="{x:Static langs:Lang.TitleDemoStr2}" controls:InfoElement.Necessary="True" Margin="0,32,0,0"/>
<controls:PasswordBox ShowClearButton="True" Width="380" controls:InfoElement.TitleWidth="140" controls:InfoElement.TitleAlignment="Left" controls:InfoElement.Title="{x:Static langs:Lang.TitleDemoStr3}" Margin="0,32,0,0" Password="123456"/>
<controls:PasswordBox Width="380" controls:InfoElement.TitleWidth="140" controls:InfoElement.Placeholder="{x:Static langs:Lang.PlsEnterContent}" controls:InfoElement.TitleAlignment="Left" controls:InfoElement.Title="{x:Static langs:Lang.TitleDemoStr3}" controls:InfoElement.Necessary="True" Margin="0,32,0,0"/>
</StackPanel>
</controls:TransitioningContentControl>
</UserControl>
@@ -1,5 +1,4 @@
// ReSharper disable once CheckNamespace
namespace HandyControlDemo.UserControl
namespace HandyControlDemo.UserControl
{
public partial class PasswordBoxDemoCtl
{
@@ -65,7 +65,7 @@
<Image Source="../../Resources/Img/LeftMainContent/ComboBox_16x.png"/>
</controls:EdgeElement.LeftContent>
</ListBoxItem>
<ListBoxItem Tag="{x:Static data:MessageToken.PasswordBoxDemoCtl}" Content="{x:Static langs:Lang.PasswordBox}">
<ListBoxItem Tag="{x:Static data:MessageToken.NaivePasswordBoxDemoCtl}" Content="{x:Static langs:Lang.PasswordBox}">
<controls:EdgeElement.LeftContent>
<Image Source="../../Resources/Img/LeftMainContent/PasswordBox_16x.png"/>
</controls:EdgeElement.LeftContent>
@@ -139,6 +139,11 @@
<Image Source="../../Resources/Img/LeftMainContent/ComboBox_16x.png"/>
</controls:EdgeElement.LeftContent>
</ListBoxItem>
<ListBoxItem Style="{StaticResource ListBoxItemNew}" Tag="{x:Static data:MessageToken.PasswordBoxDemoCtl}" Content="{x:Static langs:Lang.PasswordBox}">
<controls:EdgeElement.LeftContent>
<Image Source="../../Resources/Img/LeftMainContent/PasswordBox_16x.png"/>
</controls:EdgeElement.LeftContent>
</ListBoxItem>
<ListBoxItem Tag="{x:Static data:MessageToken.CirclePanelDemoCtl}" Content="{x:Static langs:Lang.CirclePanel}">
<controls:EdgeElement.LeftContent>
<Image Source="../../Resources/Img/LeftMainContent/ColorWheel_16x.png"/>
@@ -1,4 +1,4 @@
<UserControl x:Class="HandyControlDemo.UserControl.PasswordBoxDemoCtl"
<UserControl x:Class="HandyControlDemo.UserControl.NaivePasswordBoxDemoCtl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:HandyControl.Controls;assembly=HandyControl"
@@ -0,0 +1,10 @@
namespace HandyControlDemo.UserControl
{
public partial class NaivePasswordBoxDemoCtl
{
public NaivePasswordBoxDemoCtl()
{
InitializeComponent();
}
}
}