From 82b5def2e1ff20ab53b8fafaa03a325a4c2c8c02 Mon Sep 17 00:00:00 2001 From: Ramez Ragaa Date: Wed, 18 Dec 2024 23:17:45 +0200 Subject: [PATCH 1/2] fix(textbox): fix TextProperty change propagation in xBind --- src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.cs b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.cs index 8af394c29f34..66877fdf53f5 100644 --- a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.cs +++ b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.cs @@ -328,7 +328,14 @@ protected virtual void OnTextChanged(DependencyPropertyChangedEventArgs e) var focusManager = VisualTree.GetFocusManagerForElement(this); if (focusManager?.FocusedElement != this && - GetBindingExpression(TextProperty) is { ParentBinding.UpdateSourceTrigger: UpdateSourceTrigger.Default or UpdateSourceTrigger.LostFocus } bindingExpression) + GetBindingExpression(TextProperty) is + { + ParentBinding: + { + IsXBind: false, // NOTE: we UpdateSource in OnTextChanged only when the binding is not an x:Bind. WinUI's generated code for x:Bind contains a simple LostFocus subscription and waits for the next LostFocus even when not focused, unlike regular Bindings. + UpdateSourceTrigger: UpdateSourceTrigger.Default or UpdateSourceTrigger.LostFocus + } + } bindingExpression) { bindingExpression.UpdateSource(Text); } @@ -994,7 +1001,7 @@ private void OnFocusStateChanged(FocusState oldValue, FocusState newValue, bool UpdateButtonStates(); - if (oldValue == FocusState.Unfocused || newValue == FocusState.Unfocused) + if (newValue == FocusState.Unfocused) { _hasTextChangedThisFocusSession = false; } From 55f772d3a30f8653d44953115af4fa3b81030842 Mon Sep 17 00:00:00 2001 From: Ramez Ragaa Date: Wed, 18 Dec 2024 23:19:42 +0200 Subject: [PATCH 2/2] test: update When_TwoWay_Text_Binding to add new --- .../Windows_UI_Xaml_Controls/Given_TextBox.cs | 28 +++++++++++-------- .../When_TwoWay_Text_Binding.xaml | 2 ++ .../When_TwoWay_Text_Binding.xaml.cs | 2 ++ 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_TextBox.cs b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_TextBox.cs index a34dd21378a8..31b56fd8ce12 100644 --- a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_TextBox.cs +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_TextBox.cs @@ -47,26 +47,30 @@ namespace Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Controls public partial class Given_TextBox { [TestMethod] - [DataRow(UpdateSourceTrigger.Default)] - [DataRow(UpdateSourceTrigger.PropertyChanged)] - [DataRow(UpdateSourceTrigger.Explicit)] - [DataRow(UpdateSourceTrigger.LostFocus)] - public async Task When_TwoWay_Text_Binding(UpdateSourceTrigger trigger) + [DataRow(UpdateSourceTrigger.Default, false)] + [DataRow(UpdateSourceTrigger.PropertyChanged, false)] + [DataRow(UpdateSourceTrigger.Explicit, false)] + [DataRow(UpdateSourceTrigger.LostFocus, false)] + [DataRow(UpdateSourceTrigger.Default, true)] + [DataRow(UpdateSourceTrigger.LostFocus, true)] + public async Task When_TwoWay_Text_Binding(UpdateSourceTrigger trigger, bool xBind) { var SUT = new When_TwoWay_Text_Binding(); - var tb = trigger switch + var tb = (trigger, xBind) switch { - UpdateSourceTrigger.Default => SUT.tbTwoWay_triggerDefault, - UpdateSourceTrigger.PropertyChanged => SUT.tbTwoWay_triggerPropertyChanged, - UpdateSourceTrigger.Explicit => SUT.tbTwoWay_triggerExplicit, - UpdateSourceTrigger.LostFocus => SUT.tbTwoWay_triggerLostFocus, + (UpdateSourceTrigger.Default, false) => SUT.tbTwoWay_triggerDefault, + (UpdateSourceTrigger.PropertyChanged, false) => SUT.tbTwoWay_triggerPropertyChanged, + (UpdateSourceTrigger.Explicit, false) => SUT.tbTwoWay_triggerExplicit, + (UpdateSourceTrigger.LostFocus, false) => SUT.tbTwoWay_triggerLostFocus, + (UpdateSourceTrigger.Default, true) => SUT.tbTwoWay_triggerDefault_xBind, + (UpdateSourceTrigger.LostFocus, true) => SUT.tbTwoWay_triggerLostFocus_xBind, _ => throw new Exception("Should not happen."), }; var expectedSetCount = 0; await UITestHelper.Load(SUT); - var vm = (When_TwoWay_Text_Binding.VM)tb.DataContext; + var vm = xBind ? SUT.VMForXBind : (When_TwoWay_Text_Binding.VM)tb.DataContext; Assert.AreNotEqual(tb, FocusManager.GetFocusedElement(SUT.XamlRoot)); @@ -75,7 +79,7 @@ public async Task When_TwoWay_Text_Binding(UpdateSourceTrigger trigger) // Change text while not focused tb.Text = "Hello"; - if (trigger != UpdateSourceTrigger.Explicit) + if (trigger is UpdateSourceTrigger.PropertyChanged || (trigger is not UpdateSourceTrigger.Explicit && !xBind)) { expectedSetCount++; } diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/When_TwoWay_Text_Binding.xaml b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/When_TwoWay_Text_Binding.xaml index e5a5af2d29cb..4a9a289edbdc 100644 --- a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/When_TwoWay_Text_Binding.xaml +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/When_TwoWay_Text_Binding.xaml @@ -13,6 +13,8 @@ + +