Skip to content

Commit cb77263

Browse files
nicolaihenriksengithub-actions[bot]MDIX-SAErapchuKeboo
authored
New feature - PasswordBox styles with "reveal password" functionality (#2828)
* Initial PasswordBox "revealed" styles There are still issues with the positioning of the floating hint when password is revealed but empty; the hint should float up, but it does not. * Fixed alignment and initial wiring up Floating hint still misplaced when password is empty and revealed * Showcasing style in sample app + alignment of reveal button Reveal button aligns with the "clear text" button for consistency. Although I think the "clear text" button is floating a little too high in 2 of the styles (but that is the same for the normal PasswordBox and TextBox styles) * Showcase that password can still be set from XAML * Change PasswordChanged event handler to weak event pattern Avoid leaking memory by replacing the regular event handler with a weak event handler. * Updated showcasing in the demo tool with a bit more stuff * Fixed CA warning * Added UI test for 3-way binding * [Icon update detected by Github Action]. Auto generated pull request. (#2830) Co-authored-by: Material Design Service Account <[email protected]> * Cursor fix (#2832) Respects a cursor set from outside, otherwise falls back to the desired defaults * Fixed embedded dialog host style (#2826) (#2829) Using materialDesign:TransitionAssist.DisableTransitions="true" duration of animation for content cover opacity should be set to 0 to skip animations at all on close dialog host * Fix for 2596 - Align left margin for error message on outlined TextBox with helper text left margin (#2820) * Fix left margin for error message on outlined TextBox The error message and helper text should have the same Margin.Left value for the outlined TextBox. * Adjusted error text left margin for filled text fields ComboBoxes, DatePicker and TimePicker all rely on the fields internally, and thus inherit these changes. * Added UI test for the filled style as well * Retain original bottom margin I want to make as few changes as possible to the original style (margin) * Let DataGridCell handle mouse events itself when already editing (#2821) * Refactoring DataGridAssist input handling (#2824) * Refactoring DataGridAssist mouse handling Rather than handling the tunneling event and "pre-processing", it now handles the (already handled - by the cell) bubbling event to perform additional actions. * Added template column example Fixed issue where it would not switch to edit on click Co-authored-by: Kevin Bost <[email protected]> * Initial PasswordBox "revealed" styles There are still issues with the positioning of the floating hint when password is revealed but empty; the hint should float up, but it does not. * Fixed alignment and initial wiring up Floating hint still misplaced when password is empty and revealed * Showcasing style in sample app + alignment of reveal button Reveal button aligns with the "clear text" button for consistency. Although I think the "clear text" button is floating a little too high in 2 of the styles (but that is the same for the normal PasswordBox and TextBox styles) * Showcase that password can still be set from XAML * Change PasswordChanged event handler to weak event pattern Avoid leaking memory by replacing the regular event handler with a weak event handler. * Updated showcasing in the demo tool with a bit more stuff * Fixed CA warning * Added UI test for 3-way binding * Resolving merge conflicts * Resolving merge conflicts * Fixing hint proxy issues with password box * Moved samples and added SMTX wrapper Also fixed a bug regarding the opacity of the PART_ClearButton which was not consistent across the styles. * Apply cursor fix Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Material Design Service Account <[email protected]> Co-authored-by: Andrey Nasonov <[email protected]> Co-authored-by: Kevin Bost <[email protected]>
1 parent 13b2483 commit cb77263

File tree

13 files changed

+982
-299
lines changed

13 files changed

+982
-299
lines changed

MainDemo.Wpf/Domain/DemoItem.cs

Lines changed: 40 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,55 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Windows;
4-
using System.Windows.Controls;
1+
namespace MaterialDesignDemo.Domain;
52

6-
namespace MaterialDesignDemo.Domain
3+
public class DemoItem : ViewModelBase
74
{
8-
public class DemoItem : ViewModelBase
9-
{
10-
private readonly Type _contentType;
11-
private readonly object? _dataContext;
5+
private readonly Type _contentType;
6+
private readonly object? _dataContext;
127

13-
private object? _content;
14-
private ScrollBarVisibility _horizontalScrollBarVisibilityRequirement;
15-
private ScrollBarVisibility _verticalScrollBarVisibilityRequirement = ScrollBarVisibility.Auto;
16-
private Thickness _marginRequirement = new(16);
8+
private object? _content;
9+
private ScrollBarVisibility _horizontalScrollBarVisibilityRequirement = ScrollBarVisibility.Auto;
10+
private ScrollBarVisibility _verticalScrollBarVisibilityRequirement = ScrollBarVisibility.Auto;
11+
private Thickness _marginRequirement = new(16);
1712

18-
public DemoItem(string name, Type contentType, IEnumerable<DocumentationLink> documentation, object? dataContext = null)
19-
{
20-
Name = name;
21-
_contentType = contentType;
22-
_dataContext = dataContext;
23-
Documentation = documentation;
24-
}
13+
public DemoItem(string name, Type contentType, IEnumerable<DocumentationLink> documentation, object? dataContext = null)
14+
{
15+
Name = name;
16+
_contentType = contentType;
17+
_dataContext = dataContext;
18+
Documentation = documentation;
19+
}
2520

26-
public string Name { get; }
21+
public string Name { get; }
2722

28-
public IEnumerable<DocumentationLink> Documentation { get; }
23+
public IEnumerable<DocumentationLink> Documentation { get; }
2924

30-
public object? Content => _content ??= CreateContent();
25+
public object? Content => _content ??= CreateContent();
3126

32-
public ScrollBarVisibility HorizontalScrollBarVisibilityRequirement
33-
{
34-
get => _horizontalScrollBarVisibilityRequirement;
35-
set => SetProperty(ref _horizontalScrollBarVisibilityRequirement, value);
36-
}
27+
public ScrollBarVisibility HorizontalScrollBarVisibilityRequirement
28+
{
29+
get => _horizontalScrollBarVisibilityRequirement;
30+
set => SetProperty(ref _horizontalScrollBarVisibilityRequirement, value);
31+
}
3732

38-
public ScrollBarVisibility VerticalScrollBarVisibilityRequirement
39-
{
40-
get => _verticalScrollBarVisibilityRequirement;
41-
set => SetProperty(ref _verticalScrollBarVisibilityRequirement, value);
42-
}
33+
public ScrollBarVisibility VerticalScrollBarVisibilityRequirement
34+
{
35+
get => _verticalScrollBarVisibilityRequirement;
36+
set => SetProperty(ref _verticalScrollBarVisibilityRequirement, value);
37+
}
4338

44-
public Thickness MarginRequirement
45-
{
46-
get => _marginRequirement;
47-
set => SetProperty(ref _marginRequirement, value);
48-
}
39+
public Thickness MarginRequirement
40+
{
41+
get => _marginRequirement;
42+
set => SetProperty(ref _marginRequirement, value);
43+
}
4944

50-
private object? CreateContent()
45+
private object? CreateContent()
46+
{
47+
var content = Activator.CreateInstance(_contentType);
48+
if (_dataContext != null && content is FrameworkElement element)
5149
{
52-
var content = Activator.CreateInstance(_contentType);
53-
if (_dataContext != null && content is FrameworkElement element)
54-
{
55-
element.DataContext = _dataContext;
56-
}
57-
58-
return content;
50+
element.DataContext = _dataContext;
5951
}
52+
53+
return content;
6054
}
6155
}

MainDemo.Wpf/Domain/FieldsViewModel.cs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
namespace MaterialDesignDemo.Domain
1+
namespace MaterialDesignDemo.Domain
22
{
33
public class FieldsViewModel : ViewModelBase
44
{
55
private string? _name;
66
private string? _name2;
7+
private string? _password1 = string.Empty;
8+
private string? _password2 = "pre-filled";
9+
private string? _password1Validated = "pre-filled";
10+
private string? _password2Validated = "pre-filled";
711
private string? _text1;
812
private string? _text2;
9-
private string? _password1 = "password";
10-
private string? _password2 = "password";
1113

1214
public string? Name
1315
{
@@ -36,26 +38,47 @@ public string? Text2
3638
public string? Password1
3739
{
3840
get => _password1;
41+
set => SetProperty(ref _password1, value);
42+
}
43+
44+
public string? Password2
45+
{
46+
get => _password2;
47+
set => SetProperty(ref _password2, value);
48+
}
49+
50+
public string? Password1Validated
51+
{
52+
get => _password1Validated;
3953
set
4054
{
4155
if (string.IsNullOrEmpty(value))
4256
throw new ArgumentException("Password cannot be empty");
43-
SetProperty(ref _password1, value);
57+
SetProperty(ref _password1Validated, value);
4458
}
4559
}
4660

47-
public string? Password2
61+
public string? Password2Validated
4862
{
49-
get => _password2;
63+
get => _password2Validated;
5064
set
5165
{
5266
if (string.IsNullOrEmpty(value))
5367
throw new ArgumentException("Password cannot be empty");
54-
SetProperty(ref _password2, value);
68+
SetProperty(ref _password2Validated, value);
5569
}
5670
}
5771

5872
public FieldsTestObject TestObject => new() { Name = "Mr. Test" };
73+
74+
public ICommand SetPassword1FromViewModelCommand { get; }
75+
public ICommand SetPassword2FromViewModelCommand { get; }
76+
77+
public FieldsViewModel()
78+
{
79+
SetPassword1FromViewModelCommand = new AnotherCommandImplementation(_ => Password1 = "Set from code-behind!");
80+
SetPassword2FromViewModelCommand = new AnotherCommandImplementation(_ => Password2 = "Set from code-behind!");
81+
}
5982
}
6083

6184
public class FieldsTestObject : ViewModelBase

MainDemo.Wpf/Domain/PasswordHelper.cs

Lines changed: 0 additions & 69 deletions
This file was deleted.

MainDemo.Wpf/Fields.xaml

Lines changed: 112 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -423,9 +423,7 @@
423423
Style="{StaticResource MaterialDesignFilledPasswordBox}"
424424
materialDesign:HintAssist.Hint="Password (validated)"
425425
materialDesign:HintAssist.HelperText="Helper text"
426-
domain1:PasswordHelper.Attach="True"
427-
domain1:PasswordHelper.Password="{Binding Path=Password1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}">
428-
</PasswordBox>
426+
materialDesign:PasswordBoxAssist.Password="{Binding Path=Password1Validated, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}"/>
429427
</StackPanel>
430428
</smtx:XamlDisplay>
431429
</Grid>
@@ -570,13 +568,121 @@
570568
Style="{StaticResource MaterialDesignOutlinedPasswordBox}"
571569
materialDesign:HintAssist.Hint="Password (validated)"
572570
materialDesign:HintAssist.HelperText="Helper text"
573-
domain1:PasswordHelper.Attach="True"
574-
domain1:PasswordHelper.Password="{Binding Path=Password2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}">
575-
</PasswordBox>
571+
materialDesign:PasswordBoxAssist.Password="{Binding Path=Password2Validated, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}" />
576572
</StackPanel>
577573
</smtx:XamlDisplay>
578574
</Grid>
579575

576+
<Grid Margin="0 48 0 0">
577+
<Grid.Resources>
578+
<Style TargetType="{x:Type smtx:XamlDisplay}" BasedOn="{StaticResource {x:Type smtx:XamlDisplay}}">
579+
<Setter Property="Width" Value="200"/>
580+
<Setter Property="VerticalAlignment" Value="Top"/>
581+
<Setter Property="Margin" Value="0 0 16 0"/>
582+
</Style>
583+
584+
<Style TargetType="CheckBox" BasedOn="{StaticResource {x:Type CheckBox}}">
585+
<Setter Property="Margin" Value="0 8"/>
586+
<Setter Property="IsChecked" Value="True"/>
587+
</Style>
588+
</Grid.Resources>
589+
<Grid.ColumnDefinitions>
590+
<ColumnDefinition Width="Auto" />
591+
<ColumnDefinition Width="Auto" />
592+
<ColumnDefinition Width="Auto" />
593+
<ColumnDefinition Width="Auto" />
594+
</Grid.ColumnDefinitions>
595+
<Grid.RowDefinitions>
596+
<RowDefinition Height="Auto"/>
597+
<RowDefinition Height="100" />
598+
<RowDefinition Height="Auto" />
599+
</Grid.RowDefinitions>
600+
601+
<TextBlock
602+
Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="4"
603+
Margin="0 0 0 10"
604+
Style="{StaticResource MaterialDesignHeadline5TextBlock}"
605+
Text="'Reveal' style PasswordBoxes"/>
606+
607+
<smtx:XamlDisplay
608+
UniqueKey="reveal_password_default"
609+
Grid.Column="0"
610+
Grid.Row="1"
611+
VerticalAlignment="Top">
612+
<StackPanel>
613+
<CheckBox
614+
x:Name="RevealPasswordDefaultEnabled"
615+
Content="Enabled" />
616+
<PasswordBox
617+
Style="{StaticResource MaterialDesignRevealPasswordBox}"
618+
IsEnabled="{Binding ElementName=RevealPasswordDefaultEnabled, Path=IsChecked}"
619+
materialDesign:PasswordBoxAssist.Password="{Binding Password1, Mode=TwoWay}"
620+
materialDesign:HintAssist.Hint="Password"
621+
materialDesign:TextFieldAssist.HasClearButton="True"
622+
materialDesign:HintAssist.HelperText="Bound to Password1"/>
623+
</StackPanel>
624+
</smtx:XamlDisplay>
625+
626+
<smtx:XamlDisplay
627+
UniqueKey="reveal_password_floating"
628+
Grid.Column="1"
629+
Grid.Row="1"
630+
VerticalAlignment="Top">
631+
<StackPanel>
632+
<CheckBox
633+
x:Name="RevealPasswordFloatingEnabled"
634+
Content="Enabled" />
635+
<PasswordBox
636+
Style="{StaticResource MaterialDesignFloatingHintRevealPasswordBox}"
637+
IsEnabled="{Binding ElementName=RevealPasswordFloatingEnabled, Path=IsChecked}"
638+
materialDesign:PasswordBoxAssist.Password="{Binding Password2, Mode=TwoWay}"
639+
materialDesign:HintAssist.Hint="Password"
640+
materialDesign:TextFieldAssist.HasClearButton="True"
641+
materialDesign:HintAssist.HelperText="Bound to Password2"/>
642+
</StackPanel>
643+
</smtx:XamlDisplay>
644+
645+
<smtx:XamlDisplay
646+
UniqueKey="reveal_password_filled"
647+
Grid.Column="2"
648+
Grid.Row="1"
649+
VerticalAlignment="Top">
650+
<StackPanel>
651+
<CheckBox
652+
x:Name="RevealPasswordFilledEnabled"
653+
Content="Enabled" />
654+
<PasswordBox
655+
Style="{StaticResource MaterialDesignFilledRevealPasswordBox}"
656+
IsEnabled="{Binding ElementName=RevealPasswordFilledEnabled, Path=IsChecked}"
657+
Password="Set from XAML"
658+
materialDesign:HintAssist.Hint="Password"
659+
materialDesign:TextFieldAssist.HasClearButton="True"
660+
materialDesign:HintAssist.HelperText="Not bound password"/>
661+
</StackPanel>
662+
</smtx:XamlDisplay>
663+
664+
<smtx:XamlDisplay
665+
UniqueKey="reveal_password_outlined"
666+
Grid.Column="3"
667+
Grid.Row="1"
668+
VerticalAlignment="Top">
669+
<StackPanel>
670+
<CheckBox
671+
x:Name="RevealPasswordOutlinedEnabled"
672+
Content="Enabled" />
673+
<PasswordBox
674+
Style="{StaticResource MaterialDesignOutlinedRevealPasswordBox}"
675+
IsEnabled="{Binding ElementName=RevealPasswordOutlinedEnabled, Path=IsChecked}"
676+
materialDesign:HintAssist.Hint="Password"
677+
materialDesign:TextFieldAssist.HasClearButton="True"
678+
materialDesign:HintAssist.HelperText="Not bound password"/>
679+
</StackPanel>
680+
</smtx:XamlDisplay>
681+
682+
<Button Grid.Column="0" Grid.Row="2" Command="{Binding SetPassword1FromViewModelCommand}" Margin="0 0 45 0" Content="Set from VM" VerticalAlignment="Top" />
683+
<Button Grid.Column="1" Grid.Row="2" Command="{Binding SetPassword2FromViewModelCommand}" Margin="0 0 45 0" Content="Set from VM" VerticalAlignment="Top" />
684+
</Grid>
685+
580686
<Grid
581687
VerticalAlignment="Top"
582688
HorizontalAlignment="Left"

0 commit comments

Comments
 (0)