Skip to content
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

fix(textbox): fix TextProperty change propagation in xBind #19104

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand All @@ -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++;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
<TextBox x:Name="tbTwoWay_triggerLostFocus" Text="{Binding VMProperty, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" x:FieldModifier="public" />
<TextBox x:Name="tbTwoWay_triggerPropertyChanged" Text="{Binding VMProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" x:FieldModifier="public" />
<TextBox x:Name="tbTwoWay_triggerExplicit" Text="{Binding VMProperty, Mode=TwoWay, UpdateSourceTrigger=Explicit}" x:FieldModifier="public" />
<TextBox x:Name="tbTwoWay_triggerDefault_xBind" Text="{x:Bind VMForXBind.VMProperty, Mode=TwoWay, UpdateSourceTrigger=Default}" x:FieldModifier="public" />
<TextBox x:Name="tbTwoWay_triggerLostFocus_xBind" Text="{x:Bind VMForXBind.VMProperty, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" x:FieldModifier="public" />
<Button x:Name="dummyButton" Content="Dummy" x:FieldModifier="public" />
</StackPanel>
</Page>
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public string VMProperty
public int SetCount { get; private set; }
}

public VM VMForXBind { get; } = new VM();

public When_TwoWay_Text_Binding()
{
this.InitializeComponent();
Expand Down
11 changes: 9 additions & 2 deletions src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
ramezgerges marked this conversation as resolved.
Show resolved Hide resolved
UpdateSourceTrigger: UpdateSourceTrigger.Default or UpdateSourceTrigger.LostFocus
}
} bindingExpression)
{
bindingExpression.UpdateSource(Text);
}
Expand Down Expand Up @@ -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;
}
Expand Down
Loading