Browse Source

Fix OneWayToSource bindings with read-only properties. (#14513)

* Added more OneWayToSource tests.

One of whom is failing.

* Don't public value for OneWayToSource bindings.

Looks to have been a brainfart. This allows `OneWayToSource` bindings to read-only properties.
pull/14530/head
Steven Kirk 2 years ago
committed by GitHub
parent
commit
f6fe68eddb
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 3
      src/Avalonia.Base/Data/Core/BindingExpression.cs
  2. 67
      tests/Avalonia.Base.UnitTests/Data/Core/BindingExpressionTests.Mode.cs
  3. 14
      tests/Avalonia.Base.UnitTests/Data/Core/BindingExpressionTests.cs

3
src/Avalonia.Base/Data/Core/BindingExpression.cs

@ -375,9 +375,6 @@ internal partial class BindingExpression : UntypedBindingExpressionBase, IDescri
TryGetTarget(out var target) &&
TargetProperty is not null)
{
if (_mode is BindingMode.OneWayToSource)
PublishValue(target.GetValue(TargetProperty));
var trigger = UpdateSourceTrigger;
if (trigger is UpdateSourceTrigger.PropertyChanged)

67
tests/Avalonia.Base.UnitTests/Data/Core/BindingExpressionTests.Mode.cs

@ -1,5 +1,6 @@
using Avalonia.Data;
using Xunit;
using Xunit.Sdk;
#nullable enable
@ -67,4 +68,70 @@ public partial class BindingExpressionTests
data2.DoubleValue = 0.2;
Assert.Equal(0.5, target.Double);
}
[Fact]
public void OneWayToSource_Binding_Updates_Source_When_Target_Changes()
{
var data = new ViewModel();
var target = CreateTarget<ViewModel, string?>(
x => x.StringValue,
dataContext: data,
mode: BindingMode.OneWayToSource);
Assert.Null(data.StringValue);
target.String = "foo";
Assert.Equal("foo", data.StringValue);
}
[Fact]
public void OneWayToSource_Binding_Does_Not_Update_Target_When_Source_Changes()
{
var data = new ViewModel();
var target = CreateTarget<ViewModel, string?>(
x => x.StringValue,
dataContext: data,
mode: BindingMode.OneWayToSource);
target.String = "foo";
Assert.Equal("foo", data.StringValue);
data.StringValue = "bar";
Assert.Equal("foo", target.String);
}
[Fact]
public void OneWayToSource_Binding_Updates_Source_When_DataContext_Changes()
{
var data1 = new ViewModel();
var data2 = new ViewModel();
var target = CreateTarget<ViewModel, string?>(
x => x.StringValue,
dataContext: data1,
mode: BindingMode.OneWayToSource);
target.String = "foo";
Assert.Equal("foo", data1.StringValue);
target.DataContext = data2;
Assert.Equal("foo", data2.StringValue);
}
[Fact]
public void Can_Bind_Readonly_Property_OneWayToSource()
{
var data = new ViewModel();
var target = CreateTarget<ViewModel, string?>(
x => x.StringValue,
dataContext: data,
mode: BindingMode.OneWayToSource,
targetProperty: TargetClass.ReadOnlyStringProperty);
Assert.Equal("readonly", data.StringValue);
target.SetReadOnlyString("foo");
Assert.Equal("foo", data.StringValue);
}
}

14
tests/Avalonia.Base.UnitTests/Data/Core/BindingExpressionTests.cs

@ -343,6 +343,12 @@ public abstract partial class BindingExpressionTests
AvaloniaProperty.Register<TargetClass, object?>("Object");
public static readonly StyledProperty<string?> StringProperty =
AvaloniaProperty.Register<TargetClass, string?>("String");
public static readonly DirectProperty<TargetClass, string?> ReadOnlyStringProperty =
AvaloniaProperty.RegisterDirect<TargetClass, string?>(
nameof(ReadOnlyString),
o => o.ReadOnlyString);
private string? _readOnlyString = "readonly";
static TargetClass()
{
@ -379,10 +385,18 @@ public abstract partial class BindingExpressionTests
set => SetValue(StringProperty, value);
}
public string? ReadOnlyString
{
get => _readOnlyString;
private set => SetAndRaise(ReadOnlyStringProperty, ref _readOnlyString, value);
}
public Dictionary<AvaloniaProperty, BindingNotification> BindingNotifications { get; } = new();
public override string ToString() => nameof(TargetClass);
public void SetReadOnlyString(string? value) => ReadOnlyString = value;
protected override void UpdateDataValidation(AvaloniaProperty property, BindingValueType state, Exception? error)
{
base.UpdateDataValidation(property, state, error);

Loading…
Cancel
Save