diff --git a/src/Markup/Avalonia.Markup.Xaml/Data/Binding.cs b/src/Markup/Avalonia.Markup.Xaml/Data/Binding.cs
index 4b812e12f0..ec60695374 100644
--- a/src/Markup/Avalonia.Markup.Xaml/Data/Binding.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/Data/Binding.cs
@@ -20,6 +20,7 @@ namespace Avalonia.Markup.Xaml.Data
///
public Binding()
{
+ FallbackValue = AvaloniaProperty.UnsetValue;
}
///
@@ -27,6 +28,7 @@ namespace Avalonia.Markup.Xaml.Data
///
/// The binding path.
public Binding(string path)
+ : this()
{
Path = path;
}
@@ -122,12 +124,23 @@ namespace Avalonia.Markup.Xaml.Data
throw new NotSupportedException();
}
+ var fallback = FallbackValue;
+
+ // If we're binding to DataContext and our fallback is UnsetValue then override
+ // the fallback value to null, as broken bindings to DataContext must reset the
+ // DataContext in order to not propagate incorrect DataContexts to child controls.
+ // See Avalonia.Markup.Xaml.UnitTests.Data.DataContext_Binding_Should_Produce_Correct_Results.
+ if (targetProperty == Control.DataContextProperty && fallback == AvaloniaProperty.UnsetValue)
+ {
+ fallback = null;
+ }
+
var subject = new ExpressionSubject(
observer,
targetProperty?.PropertyType ?? typeof(object),
+ fallback,
Converter ?? DefaultValueConverter.Instance,
ConverterParameter,
- FallbackValue,
Priority);
return new InstancedBinding(subject, Mode, Priority);
diff --git a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs
index a58a8614ee..70d3f7d161 100644
--- a/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs
+++ b/src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/BindingExtension.cs
@@ -36,7 +36,7 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
public IValueConverter Converter { get; set; }
public object ConverterParameter { get; set; }
public string ElementName { get; set; }
- public object FallbackValue { get; set; }
+ public object FallbackValue { get; set; } = AvaloniaProperty.UnsetValue;
public BindingMode Mode { get; set; }
public string Path { get; set; }
public BindingPriority Priority { get; set; } = BindingPriority.LocalValue;
diff --git a/src/Markup/Avalonia.Markup/Data/ExpressionSubject.cs b/src/Markup/Avalonia.Markup/Data/ExpressionSubject.cs
index 05bf818aad..0a3be26c18 100644
--- a/src/Markup/Avalonia.Markup/Data/ExpressionSubject.cs
+++ b/src/Markup/Avalonia.Markup/Data/ExpressionSubject.cs
@@ -41,16 +41,36 @@ namespace Avalonia.Markup.Data
///
/// A parameter to pass to .
///
+ /// The binding priority.
+ public ExpressionSubject(
+ ExpressionObserver inner,
+ Type targetType,
+ IValueConverter converter,
+ object converterParameter = null,
+ BindingPriority priority = BindingPriority.LocalValue)
+ : this(inner, targetType, AvaloniaProperty.UnsetValue, converter, converterParameter, priority)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The .
+ /// The type to convert the value to.
///
/// The value to use when the binding is unable to produce a value.
///
+ /// The value converter to use.
+ ///
+ /// A parameter to pass to .
+ ///
/// The binding priority.
public ExpressionSubject(
ExpressionObserver inner,
- Type targetType,
+ Type targetType,
+ object fallbackValue,
IValueConverter converter,
object converterParameter = null,
- object fallbackValue = null,
BindingPriority priority = BindingPriority.LocalValue)
{
Contract.Requires(inner != null);
@@ -117,7 +137,7 @@ namespace Avalonia.Markup.Data
_inner.Expression,
error.Exception.Message);
- if (_fallbackValue != null)
+ if (_fallbackValue != AvaloniaProperty.UnsetValue)
{
if (TypeUtilities.TryConvert(
type,
@@ -162,7 +182,7 @@ namespace Avalonia.Markup.Data
ConverterParameter,
CultureInfo.CurrentUICulture);
- if (_fallbackValue != null &&
+ if (_fallbackValue != AvaloniaProperty.UnsetValue &&
(converted == AvaloniaProperty.UnsetValue ||
converted is BindingError))
{
diff --git a/tests/Avalonia.Markup.UnitTests/Data/ExpressionSubjectTests.cs b/tests/Avalonia.Markup.UnitTests/Data/ExpressionSubjectTests.cs
index 9ee32149e0..8b763e7fb9 100644
--- a/tests/Avalonia.Markup.UnitTests/Data/ExpressionSubjectTests.cs
+++ b/tests/Avalonia.Markup.UnitTests/Data/ExpressionSubjectTests.cs
@@ -123,8 +123,8 @@ namespace Avalonia.Markup.UnitTests.Data
var target = new ExpressionSubject(
new ExpressionObserver(data, "DoubleValue"),
typeof(string),
- DefaultValueConverter.Instance,
- fallbackValue: "9.8");
+ "9.8",
+ DefaultValueConverter.Instance);
target.OnNext("foo");
@@ -162,7 +162,7 @@ namespace Avalonia.Markup.UnitTests.Data
new ExpressionObserver(data, "DoubleValue"),
typeof(string),
converter.Object,
- "foo");
+ converterParameter: "foo");
target.Subscribe(_ => { });
@@ -178,7 +178,7 @@ namespace Avalonia.Markup.UnitTests.Data
new ExpressionObserver(data, "DoubleValue"),
typeof(string),
converter.Object,
- "foo");
+ converterParameter: "foo");
target.OnNext("bar");