ソースを参照

Subscribe to ExpressionSubject before setting value.

The inner `ExpressionObserver` must be subscribed to as setting the
value requires the expression to be evaluated.
Steven Kirk 9 年 前
コミット
daff817ce4

+ 3 - 1
src/Markup/Avalonia.Markup/Data/ExpressionObserver.cs

@@ -123,7 +123,9 @@ namespace Avalonia.Markup.Data
         /// <param name="priority">The binding priority to use.</param>
         /// <returns>
         /// True if the value could be set; false if the expression does not evaluate to a 
-        /// property.
+        /// property. Note that the <see cref="ExpressionObserver"/> must be subscribed to
+        /// before setting the target value can work, as setting the value requires the
+        /// expression to be evaluated.
         /// </returns>
         public bool SetValue(object value, BindingPriority priority = BindingPriority.LocalValue)
         {

+ 44 - 41
src/Markup/Avalonia.Markup/Data/ExpressionSubject.cs

@@ -111,56 +111,59 @@ namespace Avalonia.Markup.Data
         /// <inheritdoc/>
         public void OnNext(object value)
         {
-            var type = _inner.ResultType;
-
-            if (type != null)
+            using (_inner.Subscribe(_ => { }))
             {
-                var converted = Converter.ConvertBack(
-                    value, 
-                    type, 
-                    ConverterParameter, 
-                    CultureInfo.CurrentUICulture);
+                var type = _inner.ResultType;
 
-                if (converted == AvaloniaProperty.UnsetValue)
-                {
-                    converted = TypeUtilities.Default(type);
-                    _inner.SetValue(converted, _priority);
-                }
-                else if (converted is BindingNotification)
+                if (type != null)
                 {
-                    var error = converted as BindingNotification;
+                    var converted = Converter.ConvertBack(
+                        value,
+                        type,
+                        ConverterParameter,
+                        CultureInfo.CurrentUICulture);
 
-                    Logger.Error(
-                        LogArea.Binding,
-                        this,
-                        "Error binding to {Expression}: {Message}",
-                        _inner.Expression,
-                        error.Error.Message);
-
-                    if (_fallbackValue != AvaloniaProperty.UnsetValue)
+                    if (converted == AvaloniaProperty.UnsetValue)
                     {
-                        if (TypeUtilities.TryConvert(
-                            type, 
-                            _fallbackValue, 
-                            CultureInfo.InvariantCulture, 
-                            out converted))
-                        {
-                            _inner.SetValue(converted, _priority);
-                        }
-                        else
+                        converted = TypeUtilities.Default(type);
+                        _inner.SetValue(converted, _priority);
+                    }
+                    else if (converted is BindingNotification)
+                    {
+                        var error = converted as BindingNotification;
+
+                        Logger.Error(
+                            LogArea.Binding,
+                            this,
+                            "Error binding to {Expression}: {Message}",
+                            _inner.Expression,
+                            error.Error.Message);
+
+                        if (_fallbackValue != AvaloniaProperty.UnsetValue)
                         {
-                            Logger.Error(
-                                LogArea.Binding,
-                                this,
-                                "Could not convert FallbackValue {FallbackValue} to {Type}",
+                            if (TypeUtilities.TryConvert(
+                                type,
                                 _fallbackValue,
-                                type);
+                                CultureInfo.InvariantCulture,
+                                out converted))
+                            {
+                                _inner.SetValue(converted, _priority);
+                            }
+                            else
+                            {
+                                Logger.Error(
+                                    LogArea.Binding,
+                                    this,
+                                    "Could not convert FallbackValue {FallbackValue} to {Type}",
+                                    _fallbackValue,
+                                    type);
+                            }
                         }
                     }
-                }
-                else
-                {
-                    _inner.SetValue(converted, _priority);
+                    else
+                    {
+                        _inner.SetValue(converted, _priority);
+                    }
                 }
             }
         }