Skip to content
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 Nov 4, 2022
4d9c233
Refactor PasswordBoxAssist to use behavior
nicolaihenriksen Nov 4, 2022
90471ba
Refactor PasswordBox reveal style TextBox focus- and text selection code
nicolaihenriksen Nov 4, 2022
0a9f4f8
Undo wrong change in TestBase
nicolaihenriksen Nov 4, 2022
bc349fa
Whitespace commit to force re-run
nicolaihenriksen Nov 4, 2022
bd746b4
Increase delay in test
nicolaihenriksen Nov 4, 2022
b282e6c
Rollback of increased test delay
nicolaihenriksen Nov 4, 2022
dda88f8
Update MaterialDesignThemes.Wpf/Behaviors/PasswordBoxRevealTextBoxBeh…
nicolaihenriksen Nov 5, 2022
7d32386
Update MaterialDesignThemes.Wpf/Behaviors/PasswordBoxRevealTextBoxBeh…
nicolaihenriksen Nov 5, 2022
e1ddcf8
Extract PasswordBoxBehavior into its own class
nicolaihenriksen Nov 5, 2022
847d6ab
Cache PropertyInfos and MethodInfos in PasswordBoxRevealTextBoxBehavior
nicolaihenriksen Nov 5, 2022
417c69c
Selecting minimum required version of dependency and updating nuspec
nicolaihenriksen Nov 5, 2022
4b78de6
Convert Password binding to opt-in feature
nicolaihenriksen Nov 6, 2022
3fdb918
File scoped namespace
nicolaihenriksen Nov 6, 2022
e89ce21
Behavior classes renames and change from internal to public
nicolaihenriksen Nov 6, 2022
21d7373
Use latest version of Xaml.Behaviors and update nuspec file
nicolaihenriksen Nov 6, 2022
da46c37
Attempting fix of pipeline
Keboo Nov 7, 2022
8124883
Adding screenshots for debugging
Keboo Nov 7, 2022
fac1639
Attempt at fixing failing UI test
nicolaihenriksen Nov 7, 2022
b52a9ce
Adding more screenshots for debugging
nicolaihenriksen Nov 7, 2022
100bad6
Activate test window on loaded event
nicolaihenriksen Nov 7, 2022
bfbd3d5
Yet another attempt at getting test window shown
nicolaihenriksen Nov 7, 2022
afbc730
Removing debugging screenshots
nicolaihenriksen Nov 7, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Cache PropertyInfos and MethodInfos in PasswordBoxRevealTextBoxBehavior
  • Loading branch information
nicolaihenriksen committed Nov 7, 2022
commit 847d6ab6c091666fbe77a656e15eff537ea38f33
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,30 @@ internal PasswordBox? PasswordBox
set => SetValue(PasswordBoxProperty, value);
}

private static PropertyInfo SelectionPropertyInfo { get; }
private static MethodInfo SelectMethodInfo { get; }
private static MethodInfo GetStartMethodInfo { get; }
private static MethodInfo GetEndMethodInfo { get; }
private static PropertyInfo GetOffsetPropertyInfo { get; }

static PasswordBoxRevealTextBoxBehavior()
{
SelectionPropertyInfo = typeof(PasswordBox).GetProperty("Selection", BindingFlags.NonPublic | BindingFlags.Instance) ?? throw new InvalidOperationException("Did not find 'Selection' property on PasswordBox");
SelectMethodInfo = typeof(PasswordBox).GetMethod("Select", BindingFlags.Instance | BindingFlags.NonPublic) ?? throw new InvalidOperationException("Did not find 'Select' method on PasswordBox");
Type iTextRange = typeof(PasswordBox).Assembly.GetType("System.Windows.Documents.ITextRange") ?? throw new InvalidOperationException("Failed to find ITextRange");
GetStartMethodInfo = iTextRange.GetProperty("Start")?.GetGetMethod() ?? throw new InvalidOperationException($"Failed to find 'Start' property on {iTextRange.FullName}");
GetEndMethodInfo = iTextRange.GetProperty("End")?.GetGetMethod() ?? throw new InvalidOperationException($"Failed to find 'End' property on {iTextRange.FullName}");
Type passwordTextPointer = typeof(PasswordBox).Assembly.GetType("System.Windows.Controls.PasswordTextPointer") ?? throw new InvalidOperationException("Failed to find PasswordTextPointer");
GetOffsetPropertyInfo = passwordTextPointer.GetProperty("Offset", BindingFlags.NonPublic | BindingFlags.Instance) ?? throw new InvalidOperationException("Failed to find 'Offset' property on PasswordTextPointer");
}

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;
var selection = SelectionPropertyInfo.GetValue(PasswordBox, null) as TextSelection;
SetSelection(AssociatedObject, selection);
}
}
Expand Down Expand Up @@ -62,11 +78,10 @@ private void AssociatedObjectOnIsVisibleChanged(object sender, DependencyPropert
private PasswordBoxSelection GetPasswordBoxSelection()
{
var selection = GetSelection(AssociatedObject);
var typeTextRange = selection?.GetType().GetInterfaces().FirstOrDefault(i => i.Name == "ITextRange");
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?;
object? start = GetStartMethodInfo.Invoke(selection, null);
object? end = GetEndMethodInfo.Invoke(selection, null);
int? startValue = GetOffsetPropertyInfo.GetValue(start, null) as int?;
int? endValue = GetOffsetPropertyInfo.GetValue(end, null) as int?;
int selectionStart = startValue ?? 0;
int selectionLength = 0;
if (endValue.HasValue)
Expand All @@ -76,17 +91,7 @@ private PasswordBoxSelection GetPasswordBoxSelection()
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 });
private void SetPasswordBoxSelection(int selectionStart, int selectionLength) => SelectMethodInfo.Invoke(PasswordBox, new object[] { selectionStart, selectionLength });

private struct PasswordBoxSelection
{
public readonly int SelectionStart;
public readonly int SelectionEnd;

public PasswordBoxSelection(int selectionStart, int selectionEnd)
{
SelectionStart = selectionStart;
SelectionEnd = selectionEnd;
}
}
private record struct PasswordBoxSelection(int SelectionStart, int SelectionEnd);
}