diff --git a/src/Avalonia.Base/AvaloniaObjectExtensions.cs b/src/Avalonia.Base/AvaloniaObjectExtensions.cs
index 0e7ccbf4f3..a61cfaf5a9 100644
--- a/src/Avalonia.Base/AvaloniaObjectExtensions.cs
+++ b/src/Avalonia.Base/AvaloniaObjectExtensions.cs
@@ -237,7 +237,7 @@ namespace Avalonia
/// can be used to provide this context.
///
/// An which can be used to cancel the binding.
- [Obsolete]
+ [Obsolete("Use AvaloniaObject.Bind(AvaloniaProperty, IBinding")]
public static IDisposable Bind(
this AvaloniaObject target,
AvaloniaProperty property,
@@ -248,20 +248,7 @@ namespace Avalonia
property = property ?? throw new ArgumentNullException(nameof(property));
binding = binding ?? throw new ArgumentNullException(nameof(binding));
- var result = binding.Initiate(
- target,
- property,
- anchor,
- property.GetMetadata(target.GetType()).EnableDataValidation ?? false);
-
- if (result != null)
- {
- return BindingOperations.Apply(target, property, result, anchor);
- }
- else
- {
- return Disposable.Empty;
- }
+ return target.Bind(property, binding);
}
///
@@ -384,13 +371,13 @@ namespace Avalonia
object? anchor = null,
bool enableDataValidation = false)
{
- var expression = new UntypedObservableBindingExpression(_source);
+ var expression = new UntypedObservableBindingExpression(_source, BindingPriority.LocalValue);
return new InstancedBinding(expression, BindingMode.OneWay, BindingPriority.LocalValue);
}
- IBindingExpression IBinding2.Instance(AvaloniaObject target, AvaloniaProperty property)
+ BindingExpressionBase IBinding2.Instance(AvaloniaObject target, AvaloniaProperty property)
{
- return new UntypedObservableBindingExpression(_source);
+ return new UntypedObservableBindingExpression(_source, BindingPriority.LocalValue);
}
}
diff --git a/src/Avalonia.Base/Data/Core/BindingExpression.cs b/src/Avalonia.Base/Data/Core/BindingExpression.cs
index d04b067990..22be30b4b3 100644
--- a/src/Avalonia.Base/Data/Core/BindingExpression.cs
+++ b/src/Avalonia.Base/Data/Core/BindingExpression.cs
@@ -43,6 +43,7 @@ internal partial class BindingExpression : UntypedBindingExpressionBase, IDescri
/// Whether data validation should be enabled for the binding.
///
/// The binding mode.
+ /// The binding priority.
/// The format string to use.
/// The null target value.
///
@@ -57,10 +58,11 @@ internal partial class BindingExpression : UntypedBindingExpressionBase, IDescri
object? converterParameter = null,
bool enableDataValidation = false,
BindingMode mode = BindingMode.OneWay,
+ BindingPriority priority = BindingPriority.LocalValue,
string? stringFormat = null,
object? targetNullValue = null,
TargetTypeConverter? targetTypeConverter = null)
- : base(enableDataValidation)
+ : base(priority, enableDataValidation)
{
if (mode == BindingMode.Default)
throw new ArgumentException("Binding mode cannot be Default.", nameof(mode));
@@ -154,6 +156,7 @@ internal partial class BindingExpression : UntypedBindingExpressionBase, IDescri
bool enableDataValidation = false,
Optional
[PrivateApi]
public abstract class UntypedBindingExpressionBase : BindingExpressionBase,
- IBindingExpression,
IDisposable,
IDescription,
IValueEntry
@@ -36,9 +35,15 @@ public abstract class UntypedBindingExpressionBase : BindingExpressionBase,
///
/// Initializes a new instance of the class.
///
+ ///
+ /// The default binding priority for the expression.
+ ///
/// Whether data validation is enabled.
- public UntypedBindingExpressionBase(bool isDataValidationEnabled = false)
+ public UntypedBindingExpressionBase(
+ BindingPriority defaultPriority,
+ bool isDataValidationEnabled = false)
{
+ Priority = defaultPriority;
_isDataValidationEnabled = isDataValidationEnabled;
}
@@ -65,6 +70,10 @@ public abstract class UntypedBindingExpressionBase : BindingExpressionBase,
///
/// Gets the priority of the binding expression.
///
+ ///
+ /// Before being attached to a value store, this property describes the default priority of the
+ /// binding expression; this may change when the expression is attached to a value store.
+ ///
public BindingPriority Priority { get; private set; }
///
@@ -92,7 +101,7 @@ public abstract class UntypedBindingExpressionBase : BindingExpressionBase,
///
/// Terminates the binding.
///
- public virtual void Dispose()
+ public override void Dispose()
{
if (_sink is null)
return;
@@ -144,7 +153,7 @@ public abstract class UntypedBindingExpressionBase : BindingExpressionBase,
///
/// Starts the binding expression following a call to
- /// .
+ /// .
///
public void Start() => Start(produceValue: true);
@@ -177,28 +186,13 @@ public abstract class UntypedBindingExpressionBase : BindingExpressionBase,
void IValueEntry.Unsubscribe() => Stop();
- ///
- /// Attaches the binding expression to a subscriber with the specified subscriber but does not
- /// start it.
- ///
- /// The subscriber.
- /// The target object.
- /// The target property.
- /// The priority of the binding.
- internal void Attach(
- IBindingExpressionSink sink,
+ internal override void Attach(
+ ValueStore valueStore,
AvaloniaObject target,
AvaloniaProperty targetProperty,
BindingPriority priority)
{
- if (_sink is not null)
- throw new InvalidOperationException("BindingExpression was already attached.");
-
- _sink = sink;
- _target = new(target);
- TargetProperty = targetProperty;
- TargetType = targetProperty.PropertyType;
- Priority = priority;
+ AttachCore(valueStore, target, targetProperty, priority);
}
///
@@ -215,7 +209,7 @@ public abstract class UntypedBindingExpressionBase : BindingExpressionBase,
AvaloniaProperty targetProperty,
BindingPriority priority)
{
- Attach(subscriber, target, targetProperty, priority);
+ AttachCore(subscriber, target, targetProperty, priority);
Start(produceValue: true);
}
@@ -285,6 +279,23 @@ public abstract class UntypedBindingExpressionBase : BindingExpressionBase,
///
internal virtual bool WriteValueToSource(object? value) => false;
+ private void AttachCore(
+ IBindingExpressionSink sink,
+ AvaloniaObject target,
+ AvaloniaProperty targetProperty,
+ BindingPriority priority)
+ {
+ if (_sink is not null)
+ throw new InvalidOperationException("BindingExpression was already attached.");
+
+ _sink = sink;
+ _target = new(target);
+ TargetProperty = targetProperty;
+ TargetType = targetProperty.PropertyType;
+ Priority = priority;
+ }
+
+
///
/// Converts a value using a value converter, logging a warning if necessary.
///
diff --git a/src/Avalonia.Base/Data/Core/UntypedObservableBindingExpression.cs b/src/Avalonia.Base/Data/Core/UntypedObservableBindingExpression.cs
index 5cfac3d443..1e26caa051 100644
--- a/src/Avalonia.Base/Data/Core/UntypedObservableBindingExpression.cs
+++ b/src/Avalonia.Base/Data/Core/UntypedObservableBindingExpression.cs
@@ -8,7 +8,9 @@ internal class UntypedObservableBindingExpression : UntypedBindingExpressionBase
private IDisposable? _subscription;
public UntypedObservableBindingExpression(
- IObservable