7 changed files with 268 additions and 20 deletions
@ -0,0 +1,29 @@ |
|||
namespace Avalonia.Data; |
|||
|
|||
/// <summary>
|
|||
/// Describes the timing of binding source updates.
|
|||
/// </summary>
|
|||
public enum UpdateSourceTrigger |
|||
{ |
|||
/// <summary>
|
|||
/// The default <see cref="UpdateSourceTrigger"/> value of the binding target property.
|
|||
/// This currently defaults to <see cref="PropertyChanged"/>.
|
|||
/// </summary>
|
|||
Default, |
|||
|
|||
/// <summary>
|
|||
/// Updates the binding source immediately whenever the binding target property changes.
|
|||
/// </summary>
|
|||
PropertyChanged, |
|||
|
|||
/// <summary>
|
|||
/// Updates the binding source whenever the binding target element loses focus.
|
|||
/// </summary>
|
|||
LostFocus, |
|||
|
|||
/// <summary>
|
|||
/// Updates the binding source only when you call the
|
|||
/// <see cref="BindingExpressionBase.UpdateSource()"/> method.
|
|||
/// </summary>
|
|||
Explicit, |
|||
} |
|||
@ -0,0 +1,150 @@ |
|||
using System; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Data; |
|||
using Avalonia.UnitTests; |
|||
using Xunit; |
|||
|
|||
namespace Avalonia.Base.UnitTests.Data.Core |
|||
{ |
|||
[InvariantCulture] |
|||
public class BindingExpressionTests_UpdateSourceTrigger |
|||
{ |
|||
[Fact] |
|||
public void TwoWay_PropertyChanged_Should_Update_Source_On_Property_Changed() |
|||
{ |
|||
using var app = Start(); |
|||
var data = new ViewModel(); |
|||
var binding = new Binding |
|||
{ |
|||
Path = "Foo", |
|||
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, |
|||
}; |
|||
|
|||
var target = new TextBox { DataContext = data }; |
|||
target.Bind(TextBox.TextProperty, binding); |
|||
|
|||
var root = new TestRoot(target); |
|||
|
|||
Assert.Equal("foo", target.Text); |
|||
Assert.Equal("foo", data.Foo); |
|||
|
|||
target.Text = "bar"; |
|||
|
|||
Assert.Equal("bar", target.Text); |
|||
Assert.Equal("bar", data.Foo); |
|||
} |
|||
|
|||
[Fact] |
|||
public void TwoWay_LostFocus_Should_Update_Source_On_Lost_Focus() |
|||
{ |
|||
using var app = Start(); |
|||
var data = new ViewModel(); |
|||
var binding = new Binding |
|||
{ |
|||
Path = "Foo", |
|||
UpdateSourceTrigger = UpdateSourceTrigger.LostFocus, |
|||
}; |
|||
|
|||
var target = new TextBox { DataContext = data }; |
|||
target.Bind(TextBox.TextProperty, binding); |
|||
|
|||
var root = new TestRoot(target); |
|||
root.Focusable = true; |
|||
target.Focus(); |
|||
|
|||
Assert.Equal("foo", target.Text); |
|||
Assert.Equal("foo", data.Foo); |
|||
|
|||
target.Text = "bar"; |
|||
|
|||
Assert.Equal("bar", target.Text); |
|||
Assert.Equal("foo", data.Foo); |
|||
|
|||
root.Focus(); |
|||
|
|||
Assert.Equal("bar", target.Text); |
|||
Assert.Equal("bar", data.Foo); |
|||
} |
|||
|
|||
[Fact] |
|||
public void OneWayToSource_LostFocus_Should_Update_Source_On_Lost_Focus() |
|||
{ |
|||
using var app = Start(); |
|||
var data = new ViewModel(); |
|||
var binding = new Binding |
|||
{ |
|||
Path = "Foo", |
|||
Mode = BindingMode.OneWayToSource, |
|||
UpdateSourceTrigger = UpdateSourceTrigger.LostFocus, |
|||
}; |
|||
|
|||
var target = new TextBox { DataContext = data }; |
|||
target.Bind(TextBox.TextProperty, binding); |
|||
|
|||
var root = new TestRoot(target); |
|||
root.Focusable = true; |
|||
target.Focus(); |
|||
|
|||
Assert.Null(target.Text); |
|||
Assert.Null(data.Foo); |
|||
|
|||
target.Text = "bar"; |
|||
|
|||
Assert.Equal("bar", target.Text); |
|||
Assert.Null(data.Foo); |
|||
|
|||
root.Focus(); |
|||
|
|||
Assert.Equal("bar", target.Text); |
|||
Assert.Equal("bar", data.Foo); |
|||
} |
|||
|
|||
[Fact] |
|||
public void TwoWay_Explicit_Should_Update_Source_On_Call_To_UpdateSource() |
|||
{ |
|||
using var app = Start(); |
|||
var data = new ViewModel(); |
|||
var binding = new Binding |
|||
{ |
|||
Path = "Foo", |
|||
UpdateSourceTrigger = UpdateSourceTrigger.Explicit, |
|||
}; |
|||
|
|||
var target = new TextBox { DataContext = data }; |
|||
var expression = target.Bind(TextBox.TextProperty, binding); |
|||
|
|||
var root = new TestRoot(target); |
|||
root.Focusable = true; |
|||
target.Focus(); |
|||
|
|||
Assert.Equal("foo", target.Text); |
|||
Assert.Equal("foo", data.Foo); |
|||
|
|||
target.Text = "bar"; |
|||
|
|||
Assert.Equal("bar", target.Text); |
|||
Assert.Equal("foo", data.Foo); |
|||
|
|||
root.Focus(); |
|||
|
|||
Assert.Equal("bar", target.Text); |
|||
Assert.Equal("foo", data.Foo); |
|||
|
|||
expression.UpdateSource(); |
|||
|
|||
Assert.Equal("bar", target.Text); |
|||
Assert.Equal("bar", data.Foo); |
|||
} |
|||
|
|||
private static IDisposable Start() |
|||
{ |
|||
return UnitTestApplication.Start(TestServices.RealFocus); |
|||
} |
|||
|
|||
private class ViewModel |
|||
{ |
|||
public ViewModel(string foo = "foo") => Foo = foo; |
|||
public string Foo { get; set; } |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue