Browse Source

Added BindingExpressionBase.UpdateTarget.

refactor/bindingexpressions-in-valuestore
Steven Kirk 3 years ago
parent
commit
58db340d9a
  1. 6
      src/Avalonia.Base/Data/BindingExpressionBase.cs
  2. 13
      src/Avalonia.Base/Data/Core/BindingExpression.cs
  3. 5
      src/Avalonia.Base/Data/Core/ExpressionNodes/ExpressionNode.cs
  4. 22
      tests/Avalonia.Base.UnitTests/Data/Core/BindingExpressionTests.cs

6
src/Avalonia.Base/Data/BindingExpressionBase.cs

@ -14,8 +14,14 @@ public abstract class BindingExpressionBase : IDisposable, ISetterInstance
public virtual void Dispose()
{
GC.SuppressFinalize(this);
}
/// <summary>
/// Forces a data transfer from the binding source to the binding target.
/// </summary>
public virtual void UpdateTarget() { }
/// <summary>
/// When overridden in a derived class, attaches the binding expression to a value store but
/// does not start it.

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

@ -131,6 +131,19 @@ internal partial class BindingExpression : UntypedBindingExpressionBase, IDescri
public ExpressionNode LeafNode => _nodes[_nodes.Count - 1];
public string? StringFormat => _uncommon?._stringFormat;
public override void UpdateTarget()
{
if (_nodes.Count == 0)
return;
var source = _nodes[0].Source;
for (var i = 0; i < _nodes.Count; ++i)
_nodes[i].SetSource(null, null);
_nodes[0].SetSource(source, null);
}
/// <summary>
/// Creates an <see cref="BindingExpression"/> from an expression tree.
/// </summary>

5
src/Avalonia.Base/Data/Core/ExpressionNodes/ExpressionNode.cs

@ -127,6 +127,9 @@ internal abstract class ExpressionNode
if (source == AvaloniaProperty.UnsetValue)
source = null;
if (source == oldSource)
return;
if (oldSource is not null)
Unsubscribe(oldSource);
@ -139,7 +142,7 @@ internal abstract class ExpressionNode
// binding change.
_value = BindingExpression._nullReference;
}
else if (source != oldSource)
else
{
try { OnSourceChanged(source, dataValidationError); }
catch (Exception e) { SetError(e); }

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

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.Reactive.Linq;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Avalonia.Data.Core;
@ -271,6 +272,22 @@ namespace Avalonia.Base.UnitTests.Data.Core
GC.KeepAlive(data);
}
[Fact]
public void Can_Use_UpdateTarget_To_Update_From_Non_INPC_Data()
{
var data = new NonInpcClass { StringValue = "foo" };
var target = new Control { DataContext = data };
var expression = target.Bind(Control.TagProperty, new Binding(nameof(data.StringValue)));
Assert.Equal("foo", target.Tag);
data.StringValue = "bar";
Assert.Equal("foo", target.Tag);
expression.UpdateTarget();
Assert.Equal("bar", target.Tag);
}
private class Class1 : NotifyingBase
{
private string _stringValue;
@ -289,6 +306,11 @@ namespace Avalonia.Base.UnitTests.Data.Core
}
}
private class NonInpcClass
{
public string StringValue { get; set; }
}
private class TargetProperties : AvaloniaObject
{
public static readonly StyledProperty<double> DoubleProperty =

Loading…
Cancel
Save