add ShowPassword Property for PassordBox

now we can show or hide password with toggle button
This commit is contained in:
Mahdi Hosseini 2018-12-09 22:37:33 +03:30
parent a581a0bd73
commit 6703642064
5 changed files with 176 additions and 10 deletions

View File

@ -50,5 +50,89 @@ namespace HandyControl.Controls
SetPasswordLength(passwordBox, passwordBox.Password.Length);
}
}
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.RegisterAttached("Password",
typeof(string), typeof(PasswordBoxMonitor),
new FrameworkPropertyMetadata(string.Empty, OnPasswordPropertyChanged));
public static readonly DependencyProperty AttachProperty =
DependencyProperty.RegisterAttached("Attach",
typeof(bool), typeof(PasswordBoxMonitor), new PropertyMetadata(false, Attach));
private static readonly DependencyProperty IsUpdatingProperty =
DependencyProperty.RegisterAttached("IsUpdating", typeof(bool),
typeof(PasswordBoxMonitor));
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)
{
System.Windows.Controls.PasswordBox passwordBox = sender as System.Windows.Controls.PasswordBox;
passwordBox.PasswordChanged -= MyPasswordChanged;
if (!(bool)GetIsUpdating(passwordBox))
{
passwordBox.Password = (string)e.NewValue;
}
passwordBox.PasswordChanged += MyPasswordChanged;
}
private static void Attach(DependencyObject sender,
DependencyPropertyChangedEventArgs e)
{
System.Windows.Controls.PasswordBox passwordBox = sender as System.Windows.Controls.PasswordBox;
if (passwordBox == null)
return;
if ((bool)e.OldValue)
{
passwordBox.PasswordChanged -= MyPasswordChanged;
}
if ((bool)e.NewValue)
{
passwordBox.PasswordChanged += MyPasswordChanged;
}
}
private static void MyPasswordChanged(object sender, RoutedEventArgs e)
{
System.Windows.Controls.PasswordBox passwordBox = sender as System.Windows.Controls.PasswordBox;
SetIsUpdating(passwordBox, true);
SetPassword(passwordBox, passwordBox.Password);
SetIsUpdating(passwordBox, false);
}
}
}

View File

@ -47,6 +47,9 @@ namespace HandyControl.Controls
public static readonly DependencyProperty ShowClearButtonProperty = DependencyProperty.Register(
"ShowClearButton", typeof(bool), typeof(PasswordBox), new PropertyMetadata(ValueBoxes.FalseBox));
public static readonly DependencyProperty ShowPasswordProperty = DependencyProperty.Register(
"ShowPassword", typeof(bool), typeof(PasswordBox), new PropertyMetadata(ValueBoxes.FalseBox));
private string _password;
private char _passwordChar;
@ -109,6 +112,12 @@ namespace HandyControl.Controls
set => SetValue(ShowClearButtonProperty, value);
}
public bool ShowPassword
{
get => (bool)GetValue(ShowPasswordProperty);
set => SetValue(ShowPasswordProperty, value);
}
public virtual bool VerifyData()
{
OperationResult<bool> result;
@ -156,15 +165,13 @@ namespace HandyControl.Controls
}
}
}
public void Paste() => ActualPasswordBox.Paste();
public void SelectAll() => ActualPasswordBox.SelectAll();
public void Clear() => ActualPasswordBox.SelectAll();
private void PasswordBox_PasswordChanged(object sender, RoutedEventArgs e)
{
VerifyData();

View File

@ -33,5 +33,6 @@
<Geometry x:Key="AskGeometry">M512 0 30.11843 240.941297l0 542.117406 481.88157 240.941297 481.88157-240.941297L993.88157 240.941297 512 0zM575.776472 768.799969 460.188012 768.799969 460.188012 656.222073l115.588459 0L575.776472 768.799969zM623.335603 509.329685c-52.375829 36.723353-59.600363 55.988096-59.600363 84.885211l0 19.866447L468.616977 614.081343l0-26.489278c0-45.754021 13.846342-80.67124 61.406497-116.791866 46.957428-36.723353 57.79423-62.0082 57.79423-84.282484 0-25.284848-21.67258-54.181962-55.386393-54.181962-42.743457 0-70.436142 26.489278-82.477374 85.486914l-105.956088-21.67258c24.683144-111.976192 82.477374-157.127486 205.289345-157.127486 98.12985 0 157.72919 63.212631 157.72919 131.842639C707.017407 423.240044 688.956071 461.76953 623.335603 509.329685z</Geometry>
<Geometry x:Key="AllGeometry">M 721.005 638.949 C 758.74 638.949 789.333 669.56 789.333 707.312 C 789.333 745.047 758.74 775.657 721.005 775.657 C 683.253 775.657 652.66 745.047 652.66 707.312 C 652.66 669.56 683.253 638.949 721.005 638.949 Z M 512.017 638.949 C 549.77 638.949 580.38 669.56 580.38 707.312 C 580.38 745.047 549.77 775.657 512.017 775.657 C 474.265 775.657 443.672 745.047 443.672 707.312 C 443.672 669.56 474.265 638.949 512.017 638.949 Z M 303.029 638.949 C 340.781 638.949 371.392 669.56 371.392 707.312 C 371.392 745.047 340.781 775.657 303.029 775.657 C 265.277 775.657 234.667 745.047 234.667 707.312 C 234.667 669.56 265.277 638.949 303.029 638.949 Z M 721.005 443.655 C 758.74 443.655 789.333 474.265 789.333 512.017 C 789.333 549.769 758.74 580.363 721.005 580.363 C 683.253 580.363 652.66 549.769 652.66 512.017 C 652.66 474.265 683.253 443.655 721.005 443.655 Z M 512.017 443.655 C 549.77 443.655 580.38 474.265 580.38 512.017 C 580.38 549.769 549.77 580.363 512.017 580.363 C 474.265 580.363 443.672 549.769 443.672 512.017 C 443.672 474.265 474.265 443.655 512.017 443.655 Z M 303.029 443.655 C 340.781 443.655 371.392 474.265 371.392 512.017 C 371.392 549.769 340.781 580.363 303.029 580.363 C 265.277 580.363 234.667 549.769 234.667 512.017 C 234.667 474.265 265.277 443.655 303.029 443.655 Z M 721.005 248.343 C 758.74 248.343 789.333 278.953 789.333 316.688 C 789.333 354.44 758.74 385.051 721.005 385.051 C 683.253 385.051 652.66 354.44 652.66 316.688 C 652.66 278.953 683.253 248.343 721.005 248.343 Z M 512.017 248.343 C 549.77 248.343 580.38 278.953 580.38 316.688 C 580.38 354.44 549.77 385.051 512.017 385.051 C 474.265 385.051 443.672 354.44 443.672 316.688 C 443.672 278.953 474.265 248.343 512.017 248.343 Z M 303.029 248.343 C 340.781 248.343 371.392 278.953 371.392 316.688 C 371.392 354.44 340.781 385.051 303.029 385.051 C 265.277 385.051 234.667 354.44 234.667 316.688 C 234.667 278.953 265.277 248.343 303.029 248.343 Z</Geometry>
<Geometry x:Key="DragGeometry">M384 896C384 825.307552 440.814697 768 512 768 582.692448 768 640 824.814694 640 896 640 966.692448 583.185303 1024 512 1024 441.307552 1024 384 967.185306 384 896ZM384 512C384 441.307552 440.814697 384 512 384 582.692448 384 640 440.814697 640 512 640 582.692448 583.185303 640 512 640 441.307552 640 384 583.185303 384 512ZM384 128C384 57.307552 440.814697 0 512 0 582.692448 0 640 56.814697 640 128 640 198.692448 583.185303 256 512 256 441.307552 256 384 199.185303 384 128Z</Geometry>
<Geometry x:Key="Eye">M 16 8 C 7.664063 8 1.25 15.34375 1.25 15.34375 L 0.65625 16 L 1.25 16.65625 C 1.25 16.65625 7.097656 23.324219 14.875 23.9375 C 15.246094 23.984375 15.617188 24 16 24 C 16.382813 24 16.753906 23.984375 17.125 23.9375 C 24.902344 23.324219 30.75 16.65625 30.75 16.65625 L 31.34375 16 L 30.75 15.34375 C 30.75 15.34375 24.335938 8 16 8 Z M 16 10 C 18.203125 10 20.234375 10.601563 22 11.40625 C 22.636719 12.460938 23 13.675781 23 15 C 23 18.613281 20.289063 21.582031 16.78125 21.96875 C 16.761719 21.972656 16.738281 21.964844 16.71875 21.96875 C 16.480469 21.980469 16.242188 22 16 22 C 15.734375 22 15.476563 21.984375 15.21875 21.96875 C 11.710938 21.582031 9 18.613281 9 15 C 9 13.695313 9.351563 12.480469 9.96875 11.4375 L 9.9375 11.4375 C 11.71875 10.617188 13.773438 10 16 10 Z M 16 12 C 14.34375 12 13 13.34375 13 15 C 13 16.65625 14.34375 18 16 18 C 17.65625 18 19 16.65625 19 15 C 19 13.34375 17.65625 12 16 12 Z M 7.25 12.9375 C 7.09375 13.609375 7 14.285156 7 15 C 7 16.753906 7.5 18.394531 8.375 19.78125 C 5.855469 18.324219 4.105469 16.585938 3.53125 16 C 4.011719 15.507813 5.351563 14.203125 7.25 12.9375 Z M 24.75 12.9375 C 26.648438 14.203125 27.988281 15.507813 28.46875 16 C 27.894531 16.585938 26.144531 18.324219 23.625 19.78125 C 24.5 18.394531 25 16.753906 25 15 C 25 14.285156 24.90625 13.601563 24.75 12.9375 Z</Geometry>
<Geometry x:Key="Invisible">M 3.71875 2.28125 L 2.28125 3.71875 L 8.5 9.90625 L 19.59375 21 L 21.5 22.9375 L 28.28125 29.71875 L 29.71875 28.28125 L 23.5 22.0625 C 27.734375 19.964844 30.574219 16.851563 30.75 16.65625 L 31.34375 16 L 30.75 15.34375 C 30.480469 15.042969 24.085938 8 16 8 C 14.042969 8 12.195313 8.429688 10.5 9.0625 Z M 16 10 C 18.152344 10 20.1875 10.605469 22 11.4375 C 22.644531 12.515625 23 13.734375 23 15 C 23 16.816406 22.296875 18.476563 21.15625 19.71875 L 18.3125 16.875 C 18.730469 16.363281 19 15.714844 19 15 C 19 13.34375 17.65625 12 16 12 C 15.285156 12 14.636719 12.269531 14.125 12.6875 L 12.09375 10.65625 C 13.335938 10.273438 14.636719 10 16 10 Z M 6.6875 10.90625 C 3.480469 12.878906 1.398438 15.175781 1.25 15.34375 L 0.65625 16 L 1.25 16.65625 C 1.507813 16.945313 7.429688 23.425781 15.0625 23.9375 C 15.371094 23.96875 15.683594 24 16 24 C 16.316406 24 16.628906 23.96875 16.9375 23.9375 C 17.761719 23.882813 18.566406 23.773438 19.34375 23.59375 L 17.5625 21.8125 C 17.054688 21.929688 16.539063 22 16 22 C 12.140625 22 9 18.859375 9 15 C 9 14.46875 9.070313 13.949219 9.1875 13.4375 Z M 7.25 12.9375 C 7.089844 13.613281 7 14.300781 7 15 C 7 16.738281 7.488281 18.339844 8.34375 19.71875 C 6.054688 18.40625 4.304688 16.867188 3.40625 16 C 4.152344 15.277344 5.496094 14.078125 7.25 12.9375 Z M 24.75 12.9375 C 26.503906 14.078125 27.84375 15.277344 28.59375 16 C 27.695313 16.867188 25.917969 18.4375 23.625 19.75 C 24.484375 18.371094 25 16.738281 25 15 C 25 14.300781 24.910156 13.609375 24.75 12.9375 Z</Geometry>
</ResourceDictionary>

View File

@ -9,6 +9,8 @@
<ResourceDictionary Source="../../Basic/Geometries.xaml"/>
<ResourceDictionary Source="../TextBlock.xaml"/>
<ResourceDictionary Source="../Button.xaml"/>
<ResourceDictionary Source="../ToggleButton.xaml"/>
<ResourceDictionary Source="../TextBox.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="PasswordBoxBaseStyle" TargetType="PasswordBox">
@ -182,8 +184,34 @@
<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}"/>
<PasswordBox controls:PasswordBoxMonitor.Attach="True" controls:PasswordBoxMonitor.Password="{Binding Text, ElementName=textBox, Mode=TwoWay}" 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}">
<PasswordBox.Style>
<Style TargetType="{x:Type PasswordBox}" BasedOn="{StaticResource PasswordBoxPlusInternalStyle}">
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=ButtonEye}" Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</PasswordBox.Style>
</PasswordBox>
<TextBox Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" x:Name="textBox">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource TextBoxExtend}">
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=ButtonEye}" Value="False">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<StackPanel Name="ButtonStack" Orientation="Horizontal" Grid.Row="1" Grid.Column="1" Margin="0,0,7,0" Visibility="Collapsed">
<ToggleButton Visibility="Collapsed" Name="ButtonEye" Width="16" Style="{StaticResource ToggleButtonIconTransparent}" Padding="0,6" Margin="5,0" controls:IconSwitchElement.Geometry="{StaticResource Eye}" controls:IconSwitchElement.GeometrySelected="{StaticResource Invisible}" Foreground="{Binding BorderBrush,ElementName=PART_PasswordBox}"/>
<Button Command="interactivity:ControlCommands.Clear" Visibility="Collapsed" Name="ButtonClear" Width="16" Style="{StaticResource ButtonIcon}" Padding="0,6" controls:IconElement.Geometry="{StaticResource DeleteFillCircleGeometry}" Foreground="{Binding BorderBrush,ElementName=PART_PasswordBox}"/>
</StackPanel>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
@ -197,9 +225,19 @@
<Condition Property="IsMouseOver" Value="true"/>
<Condition Property="ShowClearButton" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" Value="Visible" TargetName="ButtonStack"/>
<Setter Property="Visibility" Value="Visible" TargetName="ButtonClear"/>
<Setter Property="Padding" Value="7,0,30,0" TargetName="PART_PasswordBox"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="true"/>
<Condition Property="ShowPassword" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" Value="Visible" TargetName="ButtonStack"/>
<Setter Property="Visibility" Value="Visible" TargetName="ButtonEye"/>
<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>
@ -232,8 +270,34 @@
<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}"/>
<PasswordBox controls:PasswordBoxMonitor.Attach="True" controls:PasswordBoxMonitor.Password="{Binding Text, ElementName=textBox, Mode=TwoWay}" 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}" >
<PasswordBox.Style>
<Style TargetType="{x:Type PasswordBox}" BasedOn="{StaticResource PasswordBoxPlusInternalStyle}">
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=ButtonEye}" Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</PasswordBox.Style>
</PasswordBox>
<TextBox Grid.Column="1" Grid.ColumnSpan="2" x:Name="textBox">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource TextBoxExtend}">
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=ButtonEye}" Value="False">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<StackPanel Margin="0,0,7,0" Grid.Column="2" Orientation="Horizontal" Visibility="Collapsed" Name="ButtonStack">
<ToggleButton Visibility="Collapsed" Margin="5,0" Name="ButtonEye" Width="16" Style="{StaticResource ToggleButtonIconTransparent}" Padding="0,6" controls:IconSwitchElement.Geometry="{StaticResource Eye}" controls:IconSwitchElement.GeometrySelected="{StaticResource Invisible}" Foreground="{Binding BorderBrush,ElementName=PART_PasswordBox}"/>
<Button Command="interactivity:ControlCommands.Clear" Visibility="Collapsed" Name="ButtonClear" Width="16" Style="{StaticResource ButtonIcon}" Padding="0,6" controls:IconElement.Geometry="{StaticResource DeleteFillCircleGeometry}" Foreground="{Binding BorderBrush,ElementName=PART_PasswordBox}"/>
</StackPanel>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
@ -247,9 +311,19 @@
<Condition Property="IsMouseOver" Value="true"/>
<Condition Property="ShowClearButton" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" Value="Visible" TargetName="ButtonStack"/>
<Setter Property="Visibility" Value="Visible" TargetName="ButtonClear"/>
<Setter Property="Padding" Value="7,0,30,0" TargetName="PART_PasswordBox"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="true"/>
<Condition Property="ShowPassword" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" Value="Visible" TargetName="ButtonStack"/>
<Setter Property="Visibility" Value="Visible" TargetName="ButtonEye"/>
<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>

View File

@ -6,8 +6,8 @@
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" ShowPassword="False" Password="123456"/>
<controls:PasswordBox Password="123456" ShowPassword="True" 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"/>