-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Refactor PasswordBoxAssist.Password to use behaviors (issue 2930) #2932
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
e9388bf
Rewrite current UI test and add new UI test to test failing scenario
nicolaihenriksen 4d9c233
Refactor PasswordBoxAssist to use behavior
nicolaihenriksen 90471ba
Refactor PasswordBox reveal style TextBox focus- and text selection code
nicolaihenriksen 0a9f4f8
Undo wrong change in TestBase
nicolaihenriksen bc349fa
Whitespace commit to force re-run
nicolaihenriksen bd746b4
Increase delay in test
nicolaihenriksen b282e6c
Rollback of increased test delay
nicolaihenriksen dda88f8
Update MaterialDesignThemes.Wpf/Behaviors/PasswordBoxRevealTextBoxBeh…
nicolaihenriksen 7d32386
Update MaterialDesignThemes.Wpf/Behaviors/PasswordBoxRevealTextBoxBeh…
nicolaihenriksen e1ddcf8
Extract PasswordBoxBehavior into its own class
nicolaihenriksen 847d6ab
Cache PropertyInfos and MethodInfos in PasswordBoxRevealTextBoxBehavior
nicolaihenriksen 417c69c
Selecting minimum required version of dependency and updating nuspec
nicolaihenriksen 4b78de6
Convert Password binding to opt-in feature
nicolaihenriksen 3fdb918
File scoped namespace
nicolaihenriksen e89ce21
Behavior classes renames and change from internal to public
nicolaihenriksen 21d7373
Use latest version of Xaml.Behaviors and update nuspec file
nicolaihenriksen da46c37
Attempting fix of pipeline
Keboo 8124883
Adding screenshots for debugging
Keboo fac1639
Attempt at fixing failing UI test
nicolaihenriksen b52a9ce
Adding more screenshots for debugging
nicolaihenriksen 100bad6
Activate test window on loaded event
nicolaihenriksen bfbd3d5
Yet another attempt at getting test window shown
nicolaihenriksen afbc730
Removing debugging screenshots
nicolaihenriksen File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Refactor PasswordBox reveal style TextBox focus- and text selection code
The old focus code did not work that well because keyboard focus was not really possible to set via the Style. With the introduction of behaviors, we can now improve that a lot.
- Loading branch information
commit 90471babd006c791fd9746f1622ee923bc4df24e
There are no files selected for viewing
92 changes: 92 additions & 0 deletions
92
MaterialDesignThemes.Wpf/Behaviors/PasswordBoxRevealTextBoxBehavior.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| using System.Reflection; | ||
| using System.Windows.Documents; | ||
| using Microsoft.Xaml.Behaviors; | ||
|
|
||
| namespace MaterialDesignThemes.Wpf.Behaviors; | ||
|
|
||
| internal class PasswordBoxRevealTextBoxBehavior : Behavior<TextBox> | ||
| { | ||
| private static readonly DependencyProperty SelectionProperty = DependencyProperty.RegisterAttached( | ||
| "Selection", typeof(TextSelection), typeof(PasswordBoxRevealTextBoxBehavior), new UIPropertyMetadata(default(TextSelection))); | ||
| private static void SetSelection(DependencyObject obj, TextSelection? value) => obj.SetValue(SelectionProperty, value); | ||
| private static TextSelection? GetSelection(DependencyObject obj) => (TextSelection?)obj.GetValue(SelectionProperty); | ||
|
|
||
| internal static readonly DependencyProperty PasswordBoxProperty = DependencyProperty.Register( | ||
| nameof(PasswordBox), typeof(PasswordBox), typeof(PasswordBoxRevealTextBoxBehavior), new PropertyMetadata(default(PasswordBox))); | ||
|
|
||
| internal PasswordBox? PasswordBox | ||
| { | ||
| get => (PasswordBox) GetValue(PasswordBoxProperty); | ||
| set => SetValue(PasswordBoxProperty, value); | ||
| } | ||
|
|
||
| protected override void OnAttached() | ||
| { | ||
| base.OnAttached(); | ||
| AssociatedObject.IsVisibleChanged += AssociatedObjectOnIsVisibleChanged; | ||
| if (PasswordBox != null) | ||
| { | ||
| var info = typeof(PasswordBox).GetProperty("Selection", BindingFlags.NonPublic | BindingFlags.Instance); | ||
| var selection = info?.GetValue(PasswordBox, null) as TextSelection; | ||
| SetSelection(AssociatedObject, selection); | ||
| } | ||
| } | ||
|
|
||
| protected override void OnDetaching() | ||
| { | ||
| base.OnDetaching(); | ||
| if (AssociatedObject != null) | ||
| { | ||
| AssociatedObject.ClearValue(SelectionProperty); | ||
| AssociatedObject.IsVisibleChanged -= AssociatedObjectOnIsVisibleChanged; | ||
| } | ||
| } | ||
|
|
||
| private void AssociatedObjectOnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) | ||
| { | ||
| if (AssociatedObject.IsVisible) | ||
| { | ||
| AssociatedObject.SelectionLength = 0; | ||
| var selection = GetPasswordBoxSelection(); | ||
| AssociatedObject.SelectionStart = selection.SelectionStart; | ||
| AssociatedObject.SelectionLength = selection.SelectionEnd; | ||
| Keyboard.Focus(AssociatedObject); | ||
| } | ||
| else if (PasswordBox != null) | ||
| { | ||
| SetPasswordBoxSelection(AssociatedObject.SelectionStart, AssociatedObject.SelectionLength); | ||
| Keyboard.Focus(PasswordBox); | ||
| } | ||
| } | ||
|
|
||
| private PasswordBoxSelection GetPasswordBoxSelection() | ||
| { | ||
| var selection = GetSelection(AssociatedObject); | ||
| var typeTextRange = selection?.GetType().GetInterfaces().FirstOrDefault(i => i.Name == "ITextRange"); | ||
nicolaihenriksen marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| object? start = typeTextRange?.GetProperty("Start")?.GetGetMethod()?.Invoke(selection, null); | ||
| object? end = typeTextRange?.GetProperty("End")?.GetGetMethod()?.Invoke(selection, null); | ||
| int? startValue = start?.GetType().GetProperty("Offset", BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(start, null) as int?; | ||
| int? endValue = end?.GetType().GetProperty("Offset", BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(end, null) as int?; | ||
| int selectionStart = startValue.GetValueOrDefault(0); | ||
nicolaihenriksen marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| int selectionLength = 0; | ||
| if (endValue.HasValue) | ||
| { | ||
| selectionLength = endValue.Value - startValue.GetValueOrDefault(0); | ||
nicolaihenriksen marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
| return new PasswordBoxSelection(selectionStart, selectionLength); | ||
| } | ||
|
|
||
| private void SetPasswordBoxSelection(int selectionStart, int selectionLength) => typeof(PasswordBox).GetMethod("Select", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(PasswordBox, new object[] { selectionStart, selectionLength }); | ||
nicolaihenriksen marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| private struct PasswordBoxSelection | ||
| { | ||
| public readonly int SelectionStart; | ||
| public readonly int SelectionEnd; | ||
|
|
||
| public PasswordBoxSelection(int selectionStart, int selectionEnd) | ||
| { | ||
| SelectionStart = selectionStart; | ||
| SelectionEnd = selectionEnd; | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.