Skip to content

Commit 1d4dc30

Browse files
Enable use of TextFieldAssist.CharacterCounterVisibility on PasswordBox (#2937)
* Add support for "character count" in PasswordBox styles * Add sample of "password input count" to demo app * Update MainDemo.Wpf/Fields.xaml Co-authored-by: Kevin B <[email protected]>
1 parent 0919177 commit 1d4dc30

File tree

3 files changed

+98
-21
lines changed

3 files changed

+98
-21
lines changed

MainDemo.Wpf/Fields.xaml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<UserControl x:Class="MaterialDesignDemo.Fields"
1+
<UserControl x:Class="MaterialDesignDemo.Fields"
22
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
33
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
44
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
@@ -339,9 +339,14 @@
339339
Grid.Column="3"
340340
VerticalAlignment="Bottom"
341341
UniqueKey="passwordFilled1">
342-
<PasswordBox materialDesign:HintAssist.HelperText="Helper text"
343-
materialDesign:HintAssist.Hint="Password"
344-
Style="{StaticResource MaterialDesignFilledPasswordBox}" />
342+
<StackPanel>
343+
<CheckBox x:Name="MaterialDesignFilledPasswordBoxTextCountComboBox" Content="View Password Input Count" />
344+
345+
<PasswordBox materialDesign:HintAssist.HelperText="Helper text"
346+
materialDesign:HintAssist.Hint="Password"
347+
materialDesign:TextFieldAssist.CharacterCounterVisibility="{Binding Path=IsChecked, ElementName=MaterialDesignFilledPasswordBoxTextCountComboBox, Converter={StaticResource BooleanToVisibilityConverter}}"
348+
Style="{StaticResource MaterialDesignFilledPasswordBox}" />
349+
</StackPanel>
345350
</smtx:XamlDisplay>
346351

347352
<smtx:XamlDisplay Grid.Row="2"

MaterialDesignThemes.Wpf/TextFieldAssist.cs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,31 @@ public static void SetCharacterCounterVisibility(DependencyObject obj, Visibilit
263263

264264
public static readonly DependencyProperty CharacterCounterVisibilityProperty =
265265
DependencyProperty.RegisterAttached("CharacterCounterVisibility", typeof(Visibility), typeof(TextFieldAssist),
266-
new PropertyMetadata(Visibility.Visible));
266+
new PropertyMetadata(Visibility.Collapsed, CharacterCounterVisibilityChanged));
267+
268+
private static void CharacterCounterVisibilityChanged(DependencyObject element, DependencyPropertyChangedEventArgs e)
269+
{
270+
if (element is PasswordBox passwordBox)
271+
{
272+
passwordBox.PasswordChanged -= PasswordBoxOnPasswordChanged;
273+
if (Equals(Visibility.Visible, e.NewValue))
274+
{
275+
SetPasswordBoxCharacterCount(passwordBox, passwordBox.SecurePassword.Length);
276+
passwordBox.PasswordChanged += PasswordBoxOnPasswordChanged;
277+
}
278+
}
279+
}
280+
281+
private static void PasswordBoxOnPasswordChanged(object sender, RoutedEventArgs e)
282+
{
283+
PasswordBox passwordBox = (PasswordBox)sender;
284+
SetPasswordBoxCharacterCount(passwordBox, passwordBox.SecurePassword.Length);
285+
}
286+
287+
internal static readonly DependencyProperty PasswordBoxCharacterCountProperty = DependencyProperty.RegisterAttached(
288+
"PasswordBoxCharacterCount", typeof(int), typeof(TextFieldAssist), new PropertyMetadata(default(int)));
289+
internal static void SetPasswordBoxCharacterCount(DependencyObject element, int value) => element.SetValue(PasswordBoxCharacterCountProperty, value);
290+
internal static int GetPasswordBoxCharacterCount(DependencyObject element) => (int) element.GetValue(PasswordBoxCharacterCountProperty);
267291

268292
#region Methods
269293

MaterialDesignThemes.Wpf/Themes/MaterialDesignTheme.PasswordBox.xaml

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,32 @@
2020
<converters:CursorConverter x:Key="ArrowCursorConverter" FallbackCursor="Arrow" />
2121
<converters:CursorConverter x:Key="IBeamCursorConverter" FallbackCursor="IBeam" />
2222

23+
<Style x:Key="MaterialDesignPasswordCharacterCounterTextBlock"
24+
TargetType="TextBlock"
25+
BasedOn="{StaticResource {x:Type TextBlock}}">
26+
<Setter Property="FontSize" Value="10" />
27+
<Setter Property="Margin" Value="0,0,16,0" />
28+
<Setter Property="Opacity" Value="0.56" />
29+
<Setter Property="Text">
30+
<Setter.Value>
31+
<MultiBinding StringFormat="{}{0} / {1}">
32+
<Binding Path="(wpf:TextFieldAssist.PasswordBoxCharacterCount)" RelativeSource="{RelativeSource FindAncestor, AncestorType=PasswordBox}" />
33+
<Binding Path="MaxLength" RelativeSource="{RelativeSource FindAncestor, AncestorType=PasswordBox}" />
34+
</MultiBinding>
35+
</Setter.Value>
36+
</Setter>
37+
<Setter Property="VerticalAlignment" Value="Center" />
38+
<Setter Property="Visibility" Value="{Binding Path=(wpf:TextFieldAssist.CharacterCounterVisibility), RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type PasswordBox}}}" />
39+
</Style>
40+
41+
<Style x:Key="MaterialDesignPasswordHelperTextBlock"
42+
TargetType="TextBlock"
43+
BasedOn="{StaticResource {x:Type TextBlock}}">
44+
<Setter Property="FontSize" Value="{Binding Path=(wpf:HintAssist.HelperTextFontSize), RelativeSource={RelativeSource Mode=TemplatedParent}}" />
45+
<Setter Property="Opacity" Value="{Binding Path=(wpf:HintAssist.HintOpacity), RelativeSource={RelativeSource Mode=TemplatedParent}}" />
46+
<Setter Property="Text" Value="{Binding Path=(wpf:HintAssist.HelperText), RelativeSource={RelativeSource Mode=TemplatedParent}}" />
47+
</Style>
48+
2349
<Style x:Key="MaterialDesignPasswordBox" TargetType="{x:Type PasswordBox}">
2450
<Setter Property="AllowDrop" Value="true" />
2551
<Setter Property="Background" Value="Transparent" />
@@ -185,12 +211,19 @@
185211
Background="{TemplateBinding wpf:TextFieldAssist.UnderlineBrush}"
186212
CornerRadius="{TemplateBinding wpf:TextFieldAssist.UnderlineCornerRadius}"
187213
Visibility="{TemplateBinding wpf:TextFieldAssist.DecorationVisibility}" />
188-
<Canvas x:Name="HelperTextWrapper" VerticalAlignment="Bottom">
189-
<TextBlock Canvas.Top="2"
190-
MaxWidth="{Binding ActualWidth, ElementName=border}"
191-
FontSize="{TemplateBinding wpf:HintAssist.HelperTextFontSize}"
192-
Opacity="{TemplateBinding wpf:HintAssist.HintOpacity}"
193-
Text="{TemplateBinding wpf:HintAssist.HelperText}" />
214+
<Canvas VerticalAlignment="Bottom">
215+
<Grid x:Name="FooterGrid"
216+
Canvas.Top="2"
217+
Width="{Binding ActualWidth, ElementName=border}">
218+
<Grid.ColumnDefinitions>
219+
<ColumnDefinition />
220+
<ColumnDefinition Width="Auto" />
221+
</Grid.ColumnDefinitions>
222+
<TextBlock x:Name="HelperTextTextBlock" Style="{Binding Path=(wpf:HintAssist.HelperTextStyle), RelativeSource={RelativeSource TemplatedParent}}" />
223+
<Border x:Name="CharacterCounterContainer" Grid.Column="1">
224+
<TextBlock x:Name="CharacterCounterTextBlock" Style="{Binding Path=(wpf:TextFieldAssist.CharacterCounterStyle), RelativeSource={RelativeSource TemplatedParent}}" />
225+
</Border>
226+
</Grid>
194227
</Canvas>
195228
</Grid>
196229
<ControlTemplate.Triggers>
@@ -232,15 +265,15 @@
232265
<Setter Property="Background" Value="{DynamicResource MaterialDesignTextFieldBoxBackground}" />
233266
<Setter Property="Padding" Value="16,8,12,8" />
234267
<Setter Property="wpf:TextFieldAssist.TextBoxViewMargin" Value="{x:Static wpf:Constants.DefaultTextBoxViewMarginEmbedded}" />
235-
<Setter TargetName="HelperTextWrapper" Property="Margin" Value="16,0,0,0" />
268+
<Setter TargetName="HelperTextTextBlock" Property="Margin" Value="16,0,0,0" />
236269
</Trigger>
237270
<Trigger Property="wpf:TextFieldAssist.HasOutlinedTextField" Value="True">
238271
<Setter Property="BorderBrush" Value="{DynamicResource MaterialDesignTextAreaBorder}" />
239272
<Setter Property="BorderThickness" Value="1" />
240273
<Setter Property="Padding" Value="16,16,12,16" />
241274
<Setter Property="VerticalContentAlignment" Value="Top" />
242275
<Setter Property="wpf:TextFieldAssist.TextBoxViewMargin" Value="{x:Static wpf:Constants.DefaultTextBoxViewMarginEmbedded}" />
243-
<Setter TargetName="HelperTextWrapper" Property="Margin" Value="16,0,0,0" />
276+
<Setter TargetName="HelperTextTextBlock" Property="Margin" Value="16,0,0,0" />
244277
<Setter TargetName="Hint" Property="FloatingOffset">
245278
<Setter.Value>
246279
<MultiBinding Converter="{StaticResource FloatingHintOffsetCalculationConverter}">
@@ -394,6 +427,7 @@
394427
</MultiTrigger.Conditions>
395428
<Setter Property="BorderBrush" Value="{DynamicResource MaterialDesignValidationErrorBrush}" />
396429
<Setter Property="BorderThickness" Value="2" />
430+
<Setter TargetName="FooterGrid" Property="Margin" Value="0,0,1,0" />
397431
<Setter TargetName="border" Property="Margin" Value="-1" />
398432
</MultiTrigger>
399433
</ControlTemplate.Triggers>
@@ -404,8 +438,11 @@
404438
<Setter Property="VerticalContentAlignment" Value="Top" />
405439
<Setter Property="internal:ClearText.HandlesClearCommand" Value="True" />
406440
<Setter Property="wpf:HintAssist.Foreground" Value="{DynamicResource PrimaryHueMidBrush}" />
441+
<Setter Property="wpf:HintAssist.HelperTextStyle" Value="{StaticResource MaterialDesignPasswordHelperTextBlock}" />
407442
<Setter Property="wpf:TextFieldAssist.TextBoxViewMargin" Value="{x:Static wpf:Constants.DefaultTextBoxViewMargin}" />
408443
<Setter Property="wpf:TextFieldAssist.UnderlineBrush" Value="{DynamicResource PrimaryHueMidBrush}" />
444+
<Setter Property="wpf:TextFieldAssist.CharacterCounterStyle" Value="{StaticResource MaterialDesignPasswordCharacterCounterTextBlock}" />
445+
<Setter Property="wpf:TextFieldAssist.CharacterCounterVisibility" Value="Hidden" />
409446
</Style>
410447

411448
<Style x:Key="MaterialDesignFloatingHintPasswordBox"
@@ -661,12 +698,19 @@
661698
Background="{TemplateBinding wpf:TextFieldAssist.UnderlineBrush}"
662699
CornerRadius="{TemplateBinding wpf:TextFieldAssist.UnderlineCornerRadius}"
663700
Visibility="{TemplateBinding wpf:TextFieldAssist.DecorationVisibility}" />
664-
<Canvas x:Name="HelperTextWrapper" VerticalAlignment="Bottom">
665-
<TextBlock Canvas.Top="2"
666-
MaxWidth="{Binding ActualWidth, ElementName=border}"
667-
FontSize="{TemplateBinding wpf:HintAssist.HelperTextFontSize}"
668-
Opacity="{TemplateBinding wpf:HintAssist.HintOpacity}"
669-
Text="{TemplateBinding wpf:HintAssist.HelperText}" />
701+
<Canvas VerticalAlignment="Bottom">
702+
<Grid x:Name="FooterGrid"
703+
Canvas.Top="2"
704+
Width="{Binding ActualWidth, ElementName=border}">
705+
<Grid.ColumnDefinitions>
706+
<ColumnDefinition />
707+
<ColumnDefinition Width="Auto" />
708+
</Grid.ColumnDefinitions>
709+
<TextBlock x:Name="HelperTextTextBlock" Style="{Binding Path=(wpf:HintAssist.HelperTextStyle), RelativeSource={RelativeSource TemplatedParent}}" />
710+
<Border x:Name="CharacterCounterContainer" Grid.Column="1">
711+
<TextBlock x:Name="CharacterCounterTextBlock" Style="{Binding Path=(wpf:TextFieldAssist.CharacterCounterStyle), RelativeSource={RelativeSource TemplatedParent}}" />
712+
</Border>
713+
</Grid>
670714
</Canvas>
671715
</Grid>
672716
<ControlTemplate.Triggers>
@@ -717,15 +761,15 @@
717761
<Setter Property="Background" Value="{DynamicResource MaterialDesignTextFieldBoxBackground}" />
718762
<Setter Property="Padding" Value="16,8,12,8" />
719763
<Setter Property="wpf:TextFieldAssist.TextBoxViewMargin" Value="{x:Static wpf:Constants.DefaultTextBoxViewMarginEmbedded}" />
720-
<Setter TargetName="HelperTextWrapper" Property="Margin" Value="16,0,0,0" />
764+
<Setter TargetName="HelperTextTextBlock" Property="Margin" Value="16,0,0,0" />
721765
</Trigger>
722766
<Trigger Property="wpf:TextFieldAssist.HasOutlinedTextField" Value="True">
723767
<Setter Property="BorderBrush" Value="{DynamicResource MaterialDesignTextAreaBorder}" />
724768
<Setter Property="BorderThickness" Value="1" />
725769
<Setter Property="Padding" Value="16,16,12,16" />
726770
<Setter Property="VerticalContentAlignment" Value="Top" />
727771
<Setter Property="wpf:TextFieldAssist.TextBoxViewMargin" Value="{x:Static wpf:Constants.DefaultTextBoxViewMarginEmbedded}" />
728-
<Setter TargetName="HelperTextWrapper" Property="Margin" Value="16,0,0,0" />
772+
<Setter TargetName="HelperTextTextBlock" Property="Margin" Value="16,0,0,0" />
729773
<Setter TargetName="Hint" Property="FloatingOffset">
730774
<Setter.Value>
731775
<MultiBinding Converter="{StaticResource FloatingHintOffsetCalculationConverter}">
@@ -880,6 +924,7 @@
880924
</MultiTrigger.Conditions>
881925
<Setter Property="BorderBrush" Value="{DynamicResource MaterialDesignValidationErrorBrush}" />
882926
<Setter Property="BorderThickness" Value="2" />
927+
<Setter TargetName="FooterGrid" Property="Margin" Value="0,0,1,0" />
883928
<Setter TargetName="border" Property="Margin" Value="-1" />
884929
</MultiTrigger>
885930

@@ -900,11 +945,14 @@
900945
<Setter Property="VerticalContentAlignment" Value="Top" />
901946
<Setter Property="internal:ClearText.HandlesClearCommand" Value="True" />
902947
<Setter Property="wpf:HintAssist.Foreground" Value="{DynamicResource PrimaryHueMidBrush}" />
948+
<Setter Property="wpf:HintAssist.HelperTextStyle" Value="{StaticResource MaterialDesignPasswordHelperTextBlock}" />
903949
<Setter Property="wpf:PasswordBoxAssist.InitialPassword" Value="" />
904950
<Setter Property="wpf:PasswordBoxAssist.IsPasswordRevealed" Value="False" />
905951
<Setter Property="wpf:PasswordBoxAssist.Password" Value="{Binding RelativeSource={RelativeSource Self}, Path=(wpf:PasswordBoxAssist.InitialPassword)}" />
906952
<Setter Property="wpf:TextFieldAssist.TextBoxViewMargin" Value="{x:Static wpf:Constants.DefaultTextBoxViewMargin}" />
907953
<Setter Property="wpf:TextFieldAssist.UnderlineBrush" Value="{DynamicResource PrimaryHueMidBrush}" />
954+
<Setter Property="wpf:TextFieldAssist.CharacterCounterStyle" Value="{StaticResource MaterialDesignPasswordCharacterCounterTextBlock}" />
955+
<Setter Property="wpf:TextFieldAssist.CharacterCounterVisibility" Value="Hidden" />
908956
</Style>
909957

910958
<Style x:Key="MaterialDesignFloatingHintRevealPasswordBox"

0 commit comments

Comments
 (0)