|
|
|
@ -183,56 +183,121 @@ namespace Avalonia.Markup.Data |
|
|
|
{ |
|
|
|
var notification = value as BindingNotification; |
|
|
|
|
|
|
|
if (notification?.HasValue == true) |
|
|
|
if (notification == null) |
|
|
|
{ |
|
|
|
value = notification.Value; |
|
|
|
} |
|
|
|
var converted = Converter.Convert( |
|
|
|
value, |
|
|
|
_targetType, |
|
|
|
ConverterParameter, |
|
|
|
CultureInfo.CurrentUICulture); |
|
|
|
|
|
|
|
var converted = Converter.Convert( |
|
|
|
value, |
|
|
|
_targetType, |
|
|
|
ConverterParameter, |
|
|
|
CultureInfo.CurrentUICulture); |
|
|
|
notification = converted as BindingNotification; |
|
|
|
|
|
|
|
if (_fallbackValue != AvaloniaProperty.UnsetValue && |
|
|
|
(converted == AvaloniaProperty.UnsetValue || |
|
|
|
converted is BindingNotification)) |
|
|
|
{ |
|
|
|
var error = converted as BindingNotification; |
|
|
|
|
|
|
|
if (TypeUtilities.TryConvert( |
|
|
|
_targetType, |
|
|
|
_fallbackValue, |
|
|
|
CultureInfo.InvariantCulture, |
|
|
|
out converted)) |
|
|
|
if (notification?.ErrorType == BindingErrorType.None) |
|
|
|
{ |
|
|
|
if (error != null) |
|
|
|
{ |
|
|
|
converted = new BindingNotification(error.Error, BindingErrorType.Error, converted); |
|
|
|
} |
|
|
|
converted = notification.Value; |
|
|
|
} |
|
|
|
else |
|
|
|
|
|
|
|
if (_fallbackValue != AvaloniaProperty.UnsetValue && |
|
|
|
(converted == AvaloniaProperty.UnsetValue || converted is BindingNotification)) |
|
|
|
{ |
|
|
|
converted = new BindingNotification( |
|
|
|
new InvalidCastException( |
|
|
|
$"Could not convert FallbackValue '{_fallbackValue}' to '{_targetType}'"), |
|
|
|
BindingErrorType.Error); |
|
|
|
var fallback = ConvertFallback(); |
|
|
|
converted = Merge(converted, fallback); |
|
|
|
} |
|
|
|
|
|
|
|
return converted; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
return ConvertValue(notification); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (notification == null) |
|
|
|
private BindingNotification ConvertValue(BindingNotification notification) |
|
|
|
{ |
|
|
|
if (notification.HasValue) |
|
|
|
{ |
|
|
|
return converted; |
|
|
|
var converted = ConvertValue(notification.Value); |
|
|
|
notification = Merge(notification, converted); |
|
|
|
} |
|
|
|
else if (_fallbackValue != AvaloniaProperty.UnsetValue) |
|
|
|
{ |
|
|
|
var fallback = ConvertFallback(); |
|
|
|
notification = Merge(notification, fallback); |
|
|
|
} |
|
|
|
|
|
|
|
return notification; |
|
|
|
} |
|
|
|
|
|
|
|
private BindingNotification ConvertFallback() |
|
|
|
{ |
|
|
|
object converted; |
|
|
|
|
|
|
|
if (_fallbackValue == AvaloniaProperty.UnsetValue) |
|
|
|
{ |
|
|
|
throw new AvaloniaInternalException("Cannot call ConvertFallback with no fallback value"); |
|
|
|
} |
|
|
|
|
|
|
|
if (TypeUtilities.TryConvert( |
|
|
|
_targetType, |
|
|
|
_fallbackValue, |
|
|
|
CultureInfo.InvariantCulture, |
|
|
|
out converted)) |
|
|
|
{ |
|
|
|
return new BindingNotification(converted); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
return new BindingNotification( |
|
|
|
new InvalidCastException( |
|
|
|
$"Could not convert FallbackValue '{_fallbackValue}' to '{_targetType}'"), |
|
|
|
BindingErrorType.Error); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private BindingNotification Merge(object a, BindingNotification b) |
|
|
|
{ |
|
|
|
var an = a as BindingNotification; |
|
|
|
|
|
|
|
if (an != null) |
|
|
|
{ |
|
|
|
if (notification.HasValue) |
|
|
|
{ |
|
|
|
notification.Value = converted; |
|
|
|
} |
|
|
|
Merge(an, b); |
|
|
|
return an; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
return b; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return notification; |
|
|
|
private BindingNotification Merge(BindingNotification a, object b) |
|
|
|
{ |
|
|
|
var bn = b as BindingNotification; |
|
|
|
|
|
|
|
if (bn != null) |
|
|
|
{ |
|
|
|
Merge(a, bn); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
a.Value = b; |
|
|
|
a.HasValue = true; |
|
|
|
} |
|
|
|
|
|
|
|
return a; |
|
|
|
} |
|
|
|
|
|
|
|
private BindingNotification Merge(BindingNotification a, BindingNotification b) |
|
|
|
{ |
|
|
|
a.Value = b.Value; |
|
|
|
a.HasValue = b.HasValue; |
|
|
|
|
|
|
|
if (b.Error != null) |
|
|
|
{ |
|
|
|
a.AddError(b.Error, b.ErrorType); |
|
|
|
} |
|
|
|
|
|
|
|
return a; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|