Skip to content

Commit

Permalink
fix(textbox): A binding on the TextBox.Text property were always tr…
Browse files Browse the repository at this point in the history
…eated as a `TwoWay` binding.

Fix #3522
  • Loading branch information
carldebilly committed Aug 18, 2020
1 parent f76368f commit d2b0b80
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 26 deletions.
5 changes: 3 additions & 2 deletions src/SamplesApp/SamplesApp.Shared/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -238,13 +238,14 @@ private void InitializeFrame(string arguments = null)
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
var startingPageType = typeof(MainPage);
if (arguments != null)
{
rootFrame.Navigate(typeof(MainPage), arguments);
rootFrame.Navigate(startingPageType, arguments);
}
else
{
rootFrame.Navigate(typeof(MainPage));
rootFrame.Navigate(startingPageType);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using FluentAssertions;
using FluentAssertions.Execution;
Expand Down Expand Up @@ -39,6 +40,44 @@ public void TextBox_NaturalSize_When_Empty_Is_Right_XPos()
sut.X.Should().Be(recth.X, "Invalid X position");
}

[Test]
[AutoRetry]
public void TextBox_UpdatedBinding_On_OneWay_Mode()
{
Run("UITests.Windows_UI_Xaml_Controls.TextBox.TextBox_Bindings");

var textboxTwoWay = _app.Marked("textboxTwoWay");
var textboxOneWay = _app.Marked("textboxOneWay");
var textboxDefault = _app.Marked("textboxDefault");

var textblock = _app.Marked("textblock");

// Initial situation
textblock.GetDependencyPropertyValue("Text").Should().Be("", "Initial should be empty");

// Enter text in two-way text
textboxTwoWay.EnterText("TwoWay Content");
textboxOneWay.FastTap();

_app.WaitForText(textblock, "TwoWay Content");

// Enter text in one-way text
textboxOneWay.EnterText("OneWay Content");
textboxDefault.FastTap();

// Ensure bound valud didn't change
Thread.Sleep(120);
_app.WaitForText(textblock, "TwoWay Content");

// Enter text in one-way text
textboxDefault.EnterText("Default Content");
textboxTwoWay.FastTap();

// Ensure bound valud didn't change
Thread.Sleep(120);
_app.WaitForText(textblock, "TwoWay Content");
}

[Test]
[AutoRetry]
public void TextBox_Foreground()
Expand Down
7 changes: 7 additions & 0 deletions src/SamplesApp/UITests.Shared/UITests.Shared.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -1045,6 +1045,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Controls\TextBox\TextBox_Bindings.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Controls\TextBox\TextBox_Binding_Null.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand Down Expand Up @@ -4022,6 +4026,9 @@
<Compile Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Controls\TextBox\TextBox_BeforeTextChanging.xaml.cs">
<DependentUpon>TextBox_BeforeTextChanging.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Controls\TextBox\TextBox_Bindings.xaml.cs">
<DependentUpon>TextBox_Bindings.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)Windows_UI_Xaml_Controls\TextBox\TextBox_Binding_Null.xaml.cs">
<DependentUpon>TextBox_Binding_Null.xaml</DependentUpon>
</Compile>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Page
x:Class="UITests.Windows_UI_Xaml_Controls.TextBox.TextBox_Bindings"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<StackPanel Spacing="10" MaxWidth="275" Margin="20">
<TextBlock FontSize="18">TextBox bound with TwoWay mode</TextBlock>
<TextBox Text="{Binding Text, Mode=TwoWay}" x:Name="textboxTwoWay" />
<TextBlock FontSize="18">TextBox bound with OneWay mode</TextBlock>
<TextBox Text="{Binding Text, Mode=OneWay}" x:Name="textboxOneWay" />
<TextBlock FontSize="18">TextBox bound with default mode (OneWay)</TextBlock>
<TextBox Text="{Binding Text}" x:Name="textboxDefault" />
<TextBlock FontSize="18">TextBlock bound on same content</TextBlock>
<TextBlock Text="{Binding Text}" x:Name="textblock" />
</StackPanel>
</Page>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.ComponentModel;
using Windows.UI.Xaml.Controls;
using Uno.UI.Samples.Controls;

namespace UITests.Windows_UI_Xaml_Controls.TextBox
{
[Sample(IgnoreInSnapshotTests=true)]
public sealed partial class TextBox_Bindings : Page
{
public TextBox_Bindings()
{
this.InitializeComponent();
DataContext = new TextBox_Bindings_Context();
}

}

[Windows.UI.Xaml.Data.Bindable]
internal class TextBox_Bindings_Context : INotifyPropertyChanged
{
private string _text;

public string Text
{
get => _text;
set
{
_text = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Text)));
}
}

public event PropertyChangedEventHandler PropertyChanged;
}
}
10 changes: 10 additions & 0 deletions src/Uno.UI/DataBinding/BindingExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ public void UpdateSource()
/// <summary>
/// Sends the current binding target value to the binding source property in TwoWay bindings.
/// </summary>
/// <remarks>
/// This method is not part of UWP contract
/// </remarks>
/// <param name="value">The expected current value of the target</param>
public void UpdateSource(object value)
{
Expand All @@ -163,6 +166,13 @@ public void UpdateSource(object value)
return;
}

if (ParentBinding.Mode != BindingMode.TwoWay)
{
// Calling this method does nothing if the Mode value of the binding is not TwoWay.
// [Microsoft documentation https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.data.bindingexpression.updatesource#remarks]
return;
}

#if !HAS_EXPENSIVE_TRYFINALLY // Try/finally incurs a very large performance hit in mono-wasm - https://github.com/mono/mono/issues/13653
try
#endif
Expand Down
48 changes: 24 additions & 24 deletions src/Uno.UI/UI/Xaml/Data/UpdateSourceTrigger.cs
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
using Uno;

namespace Windows.UI.Xaml.Data
{
/// <summary>
/// Defines constants that indicate when a binding source is updated by its binding target in two-way binding.
/// </summary>
public enum UpdateSourceTrigger
{
/// <summary>
/// Use default behavior from the dependency property that uses the binding. In Windows Runtime, this evaluates the same as a value with PropertyChanged.
/// </summary>
Default = 0,
/// <summary>
/// The binding source is updated whenever the binding target value changes. This is detected automatically by the binding system.
/// </summary>
PropertyChanged = 1,
/// <summary>
/// The binding source is updated only when you call the BindingExpression.UpdateSource method.
/// </summary>
namespace Windows.UI.Xaml.Data
{
/// <summary>
/// Defines constants that indicate when a binding source is updated by its binding target in two-way binding.
/// </summary>
public enum UpdateSourceTrigger
{
/// <summary>
/// Use default behavior from the dependency property that uses the binding. In Windows Runtime, this evaluates the same as a value with PropertyChanged.
/// </summary>
Default = 0,
/// <summary>
/// The binding source is updated whenever the binding target value changes. This is detected automatically by the binding system.
/// </summary>
PropertyChanged = 1,
/// <summary>
/// The binding source is updated only when you call the BindingExpression.UpdateSource method.
/// </summary>
Explicit = 2,
/// <summary>
/// The binding source is updated whenever the binding target element loses focus.
/// </summary>
[NotImplemented]
LostFocus = 3,
}
}

/// </summary>
[NotImplemented]
LostFocus = 3,
}
}

0 comments on commit d2b0b80

Please sign in to comment.