diff --git a/src/Core/src/Platform/Windows/MauiPasswordTextBox.cs b/src/Core/src/Platform/Windows/MauiPasswordTextBox.cs index fb2aaa9f6500..4f0536eeb689 100644 --- a/src/Core/src/Platform/Windows/MauiPasswordTextBox.cs +++ b/src/Core/src/Platform/Windows/MauiPasswordTextBox.cs @@ -56,27 +56,11 @@ static void OnPasswordPropertyChanged(DependencyObject dependencyObject, Depende bool _internalChangeFlag; int _cachedCursorPosition; int _cachedTextLength; - readonly long _token; public MauiPasswordTextBox() { TextChanging += OnNativeTextChanging; TextChanged += OnNativeTextChanged; - _token = RegisterPropertyChangedCallback(TextBox.InputScopeProperty, OnInputScopePropertyChanged); - Unloaded += (s, e) => - { - UnregisterPropertyChangedCallback(TextBox.InputScopeProperty, _token); - }; - } - - static void OnInputScopePropertyChanged(DependencyObject sender, DependencyProperty dp) - { - if (sender is not MauiPasswordTextBox mauiTxtBox || mauiTxtBox.IsPassword) - { - return; - } - - mauiTxtBox.IsPassword = mauiTxtBox.InputScope?.Names?.Any(x => x.NameValue == InputScopeNameValue.Password) ?? false; } public bool IsPassword diff --git a/src/Core/src/Platform/iOS/KeyboardExtensions.cs b/src/Core/src/Platform/iOS/KeyboardExtensions.cs index 9b7b72a3cc02..863810a4b3e1 100644 --- a/src/Core/src/Platform/iOS/KeyboardExtensions.cs +++ b/src/Core/src/Platform/iOS/KeyboardExtensions.cs @@ -43,7 +43,6 @@ public static void ApplyKeyboard(this IUITextInputTraits textInput, Keyboard key else if (keyboard == Keyboard.Password) { textInput.SetKeyboardType(UIKeyboardType.Default); - textInput.SetSecureTextEntry(true); } else if (keyboard is CustomKeyboard) { diff --git a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs index dd6324880389..ba007b2f7e8c 100644 --- a/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs +++ b/src/Core/tests/DeviceTests/Handlers/Entry/EntryHandlerTests.cs @@ -140,6 +140,70 @@ await ValidatePropertyUpdatesValue( unsetValue); } + +#if !ANDROID // Android fix is covered by PR https://github.com/dotnet/maui/pull/36280 + [Fact(DisplayName = "Password Keyboard Respects IsPassword False Initially")] + public async Task PasswordKeyboardRespectsIsPasswordFalseInitially() + { + var entry = new EntryStub() + { + Keyboard = Keyboard.Password, + IsPassword = false, + Text = "1234" + }; + + await CreateHandlerAsync(entry); + + // Initial state: Keyboard=Password but IsPassword=false → text should NOT be masked + await InvokeOnMainThreadAsync(() => + { + Assert.False(GetNativeIsPassword(entry.Handler as EntryHandler), + "Entry with Keyboard=Password and IsPassword=false should not be masked on initial load"); + }); + } + + [Fact(DisplayName = "Password Keyboard IsPassword Toggle Works Correctly")] + public async Task PasswordKeyboardIsPasswordToggleWorksCorrectly() + { + var entry = new EntryStub() + { + Keyboard = Keyboard.Password, + IsPassword = false, + Text = "1234" + }; + + await CreateHandlerAsync(entry); + + // Initial: IsPassword=false → not masked + await InvokeOnMainThreadAsync(() => + { + Assert.False(GetNativeIsPassword(entry.Handler as EntryHandler), + "Initial state: should not be masked"); + }); + + // Toggle to IsPassword=true → masked + // EntryStub is not a BindableObject, so we must explicitly call UpdateValue after changing the property. + await InvokeOnMainThreadAsync(() => + { + entry.IsPassword = true; + (entry.Handler as EntryHandler).UpdateValue(nameof(IEntry.IsPassword)); + }); + await InvokeOnMainThreadAsync(() => + Assert.True(GetNativeIsPassword(entry.Handler as EntryHandler), + "After IsPassword=true: should be masked")); + + // Toggle back to IsPassword=false → not masked + await InvokeOnMainThreadAsync(() => + { + entry.IsPassword = false; + (entry.Handler as EntryHandler).UpdateValue(nameof(IEntry.IsPassword)); + }); + await InvokeOnMainThreadAsync(() => + Assert.False(GetNativeIsPassword(entry.Handler as EntryHandler), + "After IsPassword=false: should not be masked")); + } +#endif + [Theory(DisplayName = "TextColor Updates Correctly")] [InlineData(0xFFFF0000, 0xFF0000FF)] [InlineData(0xFF0000FF, 0xFFFF0000)]